pub unsafe trait KnownLayout {
type PointerMetadata: PointerMetadata;
}
Expand description
Indicates that zerocopy can reason about certain aspects of a type’s layout.
This trait is required by many of zerocopy’s APIs. It supports sized types, slices, and slice DSTs.
§Implementation
Do not implement this trait yourself! Instead, use
#[derive(KnownLayout)]
; e.g.:
#[derive(KnownLayout)]
struct MyStruct {
...
}
#[derive(KnownLayout)]
enum MyEnum {
...
}
#[derive(KnownLayout)]
union MyUnion {
...
}
This derive performs a sophisticated analysis to deduce the layout characteristics of types. You must implement this trait via the derive.
§Dynamically-sized types
KnownLayout
supports slice-based dynamically sized types (“slice DSTs”).
A slice DST is a type whose trailing field is either a slice or another slice DST, rather than a type with fixed size. For example:
#[repr(C)]
struct PacketHeader {
...
}
#[repr(C)]
struct Packet {
header: PacketHeader,
body: [u8],
}
It can be useful to think of slice DSTs as a generalization of slices - in other words, a normal slice is just the special case of a slice DST with zero leading fields. In particular:
- Like slices, slice DSTs can have different lengths at runtime
- Like slices, slice DSTs cannot be passed by-value, but only by reference
or via other indirection such as
Box
- Like slices, a reference (or
Box
, or other pointer type) to a slice DST encodes the number of elements in the trailing slice field
§Slice DST layout
Just like other composite Rust types, the layout of a slice DST is not
well-defined unless it is specified using an explicit #[repr(...)]
attribute such as #[repr(C)]
. Other representations are
supported, but in this section, we’ll use #[repr(C)]
as our
example.
A #[repr(C)]
slice DST is laid out just like sized #[repr(C)]
types, but the presenence of a variable-length field
introduces the possibility of dynamic padding. In particular, it may be
necessary to add trailing padding after the trailing slice field in order
to satisfy the outer type’s alignment, and the amount of padding required
may be a function of the length of the trailing slice field. This is just a
natural consequence of the normal #[repr(C)]
rules applied to slice DSTs,
but it can result in surprising behavior. For example, consider the
following type:
#[repr(C)]
struct Foo {
a: u32,
b: u8,
z: [u16],
}
Assuming that u32
has alignment 4 (this is not true on all platforms),
then Foo
has alignment 4 as well. Here is the smallest possible value for
Foo
:
byte offset | 01234567
field | aaaab---
><
In this value, z
has length 0. Abiding by #[repr(C)]
, the lowest offset
that we can place z
at is 5, but since z
has alignment 2, we need to
round up to offset 6. This means that there is one byte of padding between
b
and z
, then 0 bytes of z
itself (denoted ><
in this diagram), and
then two bytes of padding after z
in order to satisfy the overall
alignment of Foo
. The size of this instance is 8 bytes.
What about if z
has length 1?
byte offset | 01234567
field | aaaab-zz
In this instance, z
has length 1, and thus takes up 2 bytes. That means
that we no longer need padding after z
in order to satisfy Foo
’s
alignment. We’ve now seen two different values of Foo
with two different
lengths of z
, but they both have the same size - 8 bytes.
What about if z
has length 2?
byte offset | 012345678901
field | aaaab-zzzz--
Now z
has length 2, and thus takes up 4 bytes. This brings our un-padded
size to 10, and so we now need another 2 bytes of padding after z
to
satisfy Foo
’s alignment.
Again, all of this is just a logical consequence of the #[repr(C)]
rules
applied to slice DSTs, but it can be surprising that the amount of trailing
padding becomes a function of the trailing slice field’s length, and thus
can only be computed at runtime.
§What is a valid size?
There are two places in zerocopy’s API that we refer to “a valid size” of a type. In normal casts or conversions, where the source is a byte slice, we need to know whether the source byte slice is a valid size of the destination type. In prefix or suffix casts, we need to know whether there exists a valid size of the destination type which fits in the source byte slice and, if so, what the largest such size is.
As outlined above, a slice DST’s size is defined by the number of elements
in its trailing slice field. However, there is not necessarily a 1-to-1
mapping between trailing slice field length and overall size. As we saw in
the previous section with the type Foo
, instances with both 0 and 1
elements in the trailing z
field result in a Foo
whose size is 8 bytes.
When we say “x is a valid size of T
”, we mean one of two things:
- If
T: Sized
, then we mean thatx == size_of::<T>()
- If
T
is a slice DST, then we mean that there exists alen
such that the instance ofT
withlen
trailing slice elements has sizex
When we say “largest possible size of T
that fits in a byte slice”, we
mean one of two things:
- If
T: Sized
, then we meansize_of::<T>()
if the byte slice is at leastsize_of::<T>()
bytes long - If
T
is a slice DST, then we mean to consider all values,len
, such that the instance ofT
withlen
trailing slice elements fits in the byte slice, and to choose the largest suchlen
, if any
§Safety
This trait does not convey any safety guarantees to code outside this crate.
You must not rely on the #[doc(hidden)]
internals of KnownLayout
. Future
releases of zerocopy may make backwards-breaking changes to these items,
including changes that only affect soundness, which may cause code which
uses those items to silently become unsound.
Required Associated Types§
Sourcetype PointerMetadata: PointerMetadata
type PointerMetadata: PointerMetadata
The type of metadata stored in a pointer to Self
.
This is ()
for sized types and usize
for slice DSTs.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementations on Foreign Types§
Source§impl KnownLayout for bool
impl KnownLayout for bool
type PointerMetadata = ()
Source§impl KnownLayout for char
impl KnownLayout for char
type PointerMetadata = ()
Source§impl KnownLayout for f32
impl KnownLayout for f32
type PointerMetadata = ()
Source§impl KnownLayout for f64
impl KnownLayout for f64
type PointerMetadata = ()
Source§impl KnownLayout for i8
impl KnownLayout for i8
type PointerMetadata = ()
Source§impl KnownLayout for i16
impl KnownLayout for i16
type PointerMetadata = ()
Source§impl KnownLayout for i32
impl KnownLayout for i32
type PointerMetadata = ()
Source§impl KnownLayout for i64
impl KnownLayout for i64
type PointerMetadata = ()
Source§impl KnownLayout for i128
impl KnownLayout for i128
type PointerMetadata = ()
Source§impl KnownLayout for isize
impl KnownLayout for isize
type PointerMetadata = ()
Source§impl KnownLayout for str
impl KnownLayout for str
type PointerMetadata = <[u8] as KnownLayout>::PointerMetadata
Source§impl KnownLayout for u8
impl KnownLayout for u8
type PointerMetadata = ()
Source§impl KnownLayout for u16
impl KnownLayout for u16
type PointerMetadata = ()
Source§impl KnownLayout for u32
impl KnownLayout for u32
type PointerMetadata = ()
Source§impl KnownLayout for u64
impl KnownLayout for u64
type PointerMetadata = ()
Source§impl KnownLayout for u128
impl KnownLayout for u128
type PointerMetadata = ()
Source§impl KnownLayout for ()
impl KnownLayout for ()
type PointerMetadata = ()
Source§impl KnownLayout for usize
impl KnownLayout for usize
type PointerMetadata = ()
Source§impl KnownLayout for __m128
Available on x86-64 and crate feature simd
only.
impl KnownLayout for __m128
simd
only.type PointerMetadata = ()
Source§impl KnownLayout for __m128d
Available on x86-64 and crate feature simd
only.
impl KnownLayout for __m128d
simd
only.type PointerMetadata = ()
Source§impl KnownLayout for __m128i
Available on x86-64 and crate feature simd
only.
impl KnownLayout for __m128i
simd
only.type PointerMetadata = ()
Source§impl KnownLayout for __m256
Available on x86-64 and crate feature simd
only.
impl KnownLayout for __m256
simd
only.type PointerMetadata = ()
Source§impl KnownLayout for __m256d
Available on x86-64 and crate feature simd
only.
impl KnownLayout for __m256d
simd
only.type PointerMetadata = ()
Source§impl KnownLayout for __m256i
Available on x86-64 and crate feature simd
only.
impl KnownLayout for __m256i
simd
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicBool
Available on target_has_atomic="8"
and rust="1.60.0"
only.
impl KnownLayout for AtomicBool
target_has_atomic="8"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicI8
Available on target_has_atomic="8"
and rust="1.60.0"
only.
impl KnownLayout for AtomicI8
target_has_atomic="8"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicI16
Available on target_has_atomic="16"
and rust="1.60.0"
only.
impl KnownLayout for AtomicI16
target_has_atomic="16"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicI32
Available on target_has_atomic="32"
and rust="1.60.0"
only.
impl KnownLayout for AtomicI32
target_has_atomic="32"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicI64
Available on target_has_atomic="64"
and rust="1.60.0"
only.
impl KnownLayout for AtomicI64
target_has_atomic="64"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicIsize
Available on target_has_atomic="ptr"
and rust="1.60.0"
only.
impl KnownLayout for AtomicIsize
target_has_atomic="ptr"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicU8
Available on target_has_atomic="8"
and rust="1.60.0"
only.
impl KnownLayout for AtomicU8
target_has_atomic="8"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicU16
Available on target_has_atomic="16"
and rust="1.60.0"
only.
impl KnownLayout for AtomicU16
target_has_atomic="16"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicU32
Available on target_has_atomic="32"
and rust="1.60.0"
only.
impl KnownLayout for AtomicU32
target_has_atomic="32"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicU64
Available on target_has_atomic="64"
and rust="1.60.0"
only.
impl KnownLayout for AtomicU64
target_has_atomic="64"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for AtomicUsize
Available on target_has_atomic="ptr"
and rust="1.60.0"
only.
impl KnownLayout for AtomicUsize
target_has_atomic="ptr"
and rust="1.60.0"
only.type PointerMetadata = ()
Source§impl KnownLayout for NonZeroI8
impl KnownLayout for NonZeroI8
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroI16
impl KnownLayout for NonZeroI16
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroI32
impl KnownLayout for NonZeroI32
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroI64
impl KnownLayout for NonZeroI64
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroI128
impl KnownLayout for NonZeroI128
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroIsize
impl KnownLayout for NonZeroIsize
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroU8
impl KnownLayout for NonZeroU8
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroU16
impl KnownLayout for NonZeroU16
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroU32
impl KnownLayout for NonZeroU32
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroU64
impl KnownLayout for NonZeroU64
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroU128
impl KnownLayout for NonZeroU128
type PointerMetadata = ()
Source§impl KnownLayout for NonZeroUsize
impl KnownLayout for NonZeroUsize
type PointerMetadata = ()
Source§impl<T> KnownLayout for Option<T>
impl<T> KnownLayout for Option<T>
type PointerMetadata = ()
Source§impl<T> KnownLayout for [T]
impl<T> KnownLayout for [T]
type PointerMetadata = usize
Source§impl<T> KnownLayout for Wrapping<T>
impl<T> KnownLayout for Wrapping<T>
type PointerMetadata = ()
Source§impl<T> KnownLayout for AtomicPtr<T>
Available on target_has_atomic="ptr"
and rust="1.60.0"
only.
impl<T> KnownLayout for AtomicPtr<T>
target_has_atomic="ptr"
and rust="1.60.0"
only.