I'm proposing adding Pod
and Packed
traits and a write_initialized
intrinsic to make it easier to work with structured low-level APIs.
Previous discussions
A sized type T
is Pod
if any [u8; sizeof(T)]
can safely be transmuted to T
.
A (possibly unsized) object is Pod
if any byte in its object representation can safely be overwritten by any other byte.
All integer types are Pod
. All raw pointers to sized types are Pod
. Arrays of Pod
types are Pod
. Tuples, structs and unions which contain only Pod
types and which do not have invariants are Pod
.
A sized type T
is Packed
if any object of type T
can safely be transmuted to [u8; sizeof(T)]
.
A (possibly unsized) object is Pod
if any byte in its object representation can safely be read as an u8
.
All integer types are Packed
. All raw pointers on currently supported platforms are Packed
. Arrays of of Packed
types are Packed
. Whether tuples, structs and unions are Packed
depends on their contents.
A Packed
trait cannot be implemented safely outside the compiler.
Pod
and Packed
traits make it possible to write safe APIs that are useful in systems programming. For example:
fn pod_zeroed<T: Pod>() -> T;
// Err if sizeof(U) != sizeof(T)
fn pod_read<T: Pod, U: Packed + ?Sized>(u: &U) -> Result<T>;
// Err if sizeof(U) < sizeof(T)
fn pod_read_init<T: Pod, U: Packed + ?Sized>(u: &U) -> Result<T>;
// Err if sizeof(U) is not a multiple of sizeof(T)
fn pod_iter<T: Pod, U: Packed + ?Sized>(u: &U) -> Result<impl Iterator<Item = T>>;
// Err if sizeof(U) != sizeof(T)
fn pod_write<T: Pod + ?Sized, U: Packed + ?Sized>(u: &U, t: &mut MaybeUninit<T>) -> Result<()>;
Pod
and Packed
do not cover all use cases that deal with transmuting between bytes and objects. For example, it would be useful if the compiler provided the following intrinsic:
/// Overwrites `t` with `u`, replacing all padding bits of `U` by an unspecified bit pattern.
/// Err if sizeof(u) != sizeof(T).
fn write_initialized<T: Pod + ?Sized, U: ?Sized>(u: &U, t: &mut MaybeUninit<T>) -> Result<()>;
This would cover the usecase of writing data structures with padding bytes into memory.
Both Packed
and Pod
would not be auto-traits. Like Copy
, every type has to opt into being Pod
or Packed
. Like Copy
the compiler would verify at compile time that
Pod
only contain other Pod
types recursivelyPacked
only contain other Packed
types and do not have padding bitsI assume that Packed
would be more controversial that Pod
due to its platform dependence.
You may want to take a look at the safe transmute working group.
A (possibly unsized) object is Pod if any byte in its object representation can safely be read as an u8.
I guess you mean Packed
here?
Yes
Most helpful comment
You may want to take a look at the safe transmute working group.