#[repr(C, packed(1))]pub struct Unalign<T>(/* private fields */);
Expand description
A type with no alignment requirement.
An Unalign
wraps a T
, removing any alignment requirement. Unalign<T>
has the same size and bit validity as T
, but not necessarily the same
alignment or ABI. This is useful if a type with an alignment requirement
needs to be read from a chunk of memory which provides no alignment
guarantees.
Since Unalign
has no alignment requirement, the inner T
may not be
properly aligned in memory. There are five ways to access the inner T
:
- by value, using
get
orinto_inner
- by reference inside of a callback, using
update
- fallibly by reference, using
try_deref
ortry_deref_mut
; these can fail if theUnalign
does not satisfyT
’s alignment requirement at runtime - unsafely by reference, using
deref_unchecked
orderef_mut_unchecked
; it is the caller’s responsibility to ensure that theUnalign
satisfiesT
’s alignment requirement - (where
T: Unaligned
) infallibly by reference, usingDeref::deref
orDerefMut::deref_mut
§Example
In this example, we need EthernetFrame
to have no alignment requirement -
and thus implement Unaligned
. EtherType
is #[repr(u16)]
and so
cannot implement Unaligned
. We use Unalign
to relax EtherType
’s
alignment requirement so that EthernetFrame
has no alignment requirement
and can implement Unaligned
.
use zerocopy::*;
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
enum EtherType {
Ipv4 = 0x0800u16.to_be(),
Arp = 0x0806u16.to_be(),
Ipv6 = 0x86DDu16.to_be(),
...
}
#[derive(TryFromBytes, KnownLayout, Immutable, Unaligned)]
#[repr(C)]
struct EthernetFrame {
src: Mac,
dst: Mac,
ethertype: Unalign<EtherType>,
payload: [u8],
}
let bytes = &[
...
0x86, 0xDD, // EtherType
0xDE, 0xAD, 0xBE, 0xEF // Payload
][..];
// PANICS: Guaranteed not to panic because `bytes` is of the right
// length, has the right contents, and `EthernetFrame` has no
// alignment requirement.
let packet = EthernetFrame::try_ref_from_bytes(&bytes).unwrap();
assert_eq!(packet.ethertype.get(), EtherType::Ipv6);
assert_eq!(packet.payload, [0xDE, 0xAD, 0xBE, 0xEF]);
§Safety
Unalign<T>
is guaranteed to have the same size and bit validity as T
,
and to have UnsafeCell
s covering the same byte ranges as T
.
Unalign<T>
is guaranteed to have alignment 1.
Implementations§
Source§impl<T> Unalign<T>
impl<T> Unalign<T>
Sourcepub const fn into_inner(self) -> T
pub const fn into_inner(self) -> T
Consumes self
, returning the inner T
.
Sourcepub fn try_deref(&self) -> Result<&T, AlignmentError<&Self, T>>
pub fn try_deref(&self) -> Result<&T, AlignmentError<&Self, T>>
Attempts to return a reference to the wrapped T
, failing if self
is
not properly aligned.
If self
does not satisfy align_of::<T>()
, then try_deref
returns
Err
.
If T: Unaligned
, then Unalign<T>
implements Deref
, and callers
may prefer Deref::deref
, which is infallible.
Sourcepub fn try_deref_mut(&mut self) -> Result<&mut T, AlignmentError<&mut Self, T>>
pub fn try_deref_mut(&mut self) -> Result<&mut T, AlignmentError<&mut Self, T>>
Attempts to return a mutable reference to the wrapped T
, failing if
self
is not properly aligned.
If self
does not satisfy align_of::<T>()
, then try_deref
returns
Err
.
If T: Unaligned
, then Unalign<T>
implements DerefMut
, and
callers may prefer DerefMut::deref_mut
, which is infallible.
Sourcepub const unsafe fn deref_unchecked(&self) -> &T
pub const unsafe fn deref_unchecked(&self) -> &T
Returns a reference to the wrapped T
without checking alignment.
If T: Unaligned
, then Unalign<T>
implements Deref
, and callers
may prefer Deref::deref
, which is safe.
§Safety
The caller must guarantee that self
satisfies align_of::<T>()
.
Sourcepub unsafe fn deref_mut_unchecked(&mut self) -> &mut T
pub unsafe fn deref_mut_unchecked(&mut self) -> &mut T
Returns a mutable reference to the wrapped T
without checking
alignment.
If T: Unaligned
, then Unalign<T>
implements DerefMut
, and
callers may prefer DerefMut::deref_mut
, which is safe.
§Safety
The caller must guarantee that self
satisfies align_of::<T>()
.
Sourcepub const fn get_ptr(&self) -> *const T
pub const fn get_ptr(&self) -> *const T
Gets an unaligned raw pointer to the inner T
.
§Safety
The returned raw pointer is not necessarily aligned to
align_of::<T>()
. Most functions which operate on raw pointers require
those pointers to be aligned, so calling those functions with the result
of get_ptr
will result in undefined behavior if alignment is not
guaranteed using some out-of-band mechanism. In general, the only
functions which are safe to call with this pointer are those which are
explicitly documented as being sound to use with an unaligned pointer,
such as read_unaligned
.
Even if the caller is permitted to mutate self
(e.g. they have
ownership or a mutable borrow), it is not guaranteed to be sound to
write through the returned pointer. If writing is required, prefer
get_mut_ptr
instead.
Sourcepub fn get_mut_ptr(&mut self) -> *mut T
pub fn get_mut_ptr(&mut self) -> *mut T
Gets an unaligned mutable raw pointer to the inner T
.
§Safety
The returned raw pointer is not necessarily aligned to
align_of::<T>()
. Most functions which operate on raw pointers require
those pointers to be aligned, so calling those functions with the result
of get_ptr
will result in undefined behavior if alignment is not
guaranteed using some out-of-band mechanism. In general, the only
functions which are safe to call with this pointer are those which are
explicitly documented as being sound to use with an unaligned pointer,
such as read_unaligned
.
Sourcepub fn update<O, F: FnOnce(&mut T) -> O>(&mut self, f: F) -> O
pub fn update<O, F: FnOnce(&mut T) -> O>(&mut self, f: F) -> O
Updates the inner T
by calling a function on it.
If T: Unaligned
, then Unalign<T>
implements DerefMut
, and that
impl should be preferred over this method when performing updates, as it
will usually be faster and more ergonomic.
For large types, this method may be expensive, as it requires copying
2 * size_of::<T>()
bytes. [1]
[1] Since the inner T
may not be aligned, it would not be sound to
invoke f
on it directly. Instead, update
moves it into a
properly-aligned location in the local stack frame, calls f
on it, and
then moves it back to its original location in self
.
Trait Implementations§
Source§impl<T> FromBytes for Unalign<T>where
T: FromBytes,
impl<T> FromBytes for Unalign<T>where
T: FromBytes,
Source§fn ref_from_bytes(source: &[u8]) -> Result<&Self, CastError<&[u8], Self>>where
Self: KnownLayout + Immutable,
fn ref_from_bytes(source: &[u8]) -> Result<&Self, CastError<&[u8], Self>>where
Self: KnownLayout + Immutable,
Source§fn ref_from_prefix(
source: &[u8],
) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>where
Self: KnownLayout + Immutable,
fn ref_from_prefix(
source: &[u8],
) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>where
Self: KnownLayout + Immutable,
Source§fn ref_from_suffix(
source: &[u8],
) -> Result<(&[u8], &Self), CastError<&[u8], Self>>where
Self: Immutable + KnownLayout,
fn ref_from_suffix(
source: &[u8],
) -> Result<(&[u8], &Self), CastError<&[u8], Self>>where
Self: Immutable + KnownLayout,
&Self
. Read moreSource§fn mut_from_bytes(
source: &mut [u8],
) -> Result<&mut Self, CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
fn mut_from_bytes(
source: &mut [u8],
) -> Result<&mut Self, CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
Source§fn mut_from_prefix(
source: &mut [u8],
) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
fn mut_from_prefix(
source: &mut [u8],
) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
Source§fn mut_from_suffix(
source: &mut [u8],
) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
fn mut_from_suffix(
source: &mut [u8],
) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
Source§fn read_from_prefix(
source: &[u8],
) -> Result<(Self, &[u8]), SizeError<&[u8], Self>>where
Self: Sized,
fn read_from_prefix(
source: &[u8],
) -> Result<(Self, &[u8]), SizeError<&[u8], Self>>where
Self: Sized,
Source§impl<T> FromZeros for Unalign<T>where
T: FromZeros,
impl<T> FromZeros for Unalign<T>where
T: FromZeros,
Source§fn new_zeroed() -> Selfwhere
Self: Sized,
fn new_zeroed() -> Selfwhere
Self: Sized,
Self
from zeroed bytes. Read moreSource§fn new_box_zeroed() -> Result<Box<Self>, AllocError>where
Self: Sized,
fn new_box_zeroed() -> Result<Box<Self>, AllocError>where
Self: Sized,
alloc
only.Box<Self>
from zeroed bytes. Read moreSource§fn new_vec_zeroed(len: usize) -> Result<Vec<Self>, AllocError>where
Self: Sized,
fn new_vec_zeroed(len: usize) -> Result<Vec<Self>, AllocError>where
Self: Sized,
alloc
only.Vec<Self>
from zeroed bytes. Read moreSource§fn extend_vec_zeroed(
v: &mut Vec<Self>,
additional: usize,
) -> Result<(), AllocError>where
Self: Sized,
fn extend_vec_zeroed(
v: &mut Vec<Self>,
additional: usize,
) -> Result<(), AllocError>where
Self: Sized,
rust="1.57.0"
and crate feature alloc
only.Vec<Self>
by pushing additional
new items onto the end of
the vector. The new items are initialized with zeros.Source§impl<T> IntoBytes for Unalign<T>where
T: IntoBytes,
impl<T> IntoBytes for Unalign<T>where
T: IntoBytes,
Source§fn as_mut_bytes(&mut self) -> &mut [u8] ⓘwhere
Self: FromBytes,
fn as_mut_bytes(&mut self) -> &mut [u8] ⓘwhere
Self: FromBytes,
Source§fn write_to(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>>where
Self: Immutable,
fn write_to(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>>where
Self: Immutable,
Source§fn write_to_prefix(
&self,
dst: &mut [u8],
) -> Result<(), SizeError<&Self, &mut [u8]>>where
Self: Immutable,
fn write_to_prefix(
&self,
dst: &mut [u8],
) -> Result<(), SizeError<&Self, &mut [u8]>>where
Self: Immutable,
Source§impl<T> KnownLayout for Unalign<T>
impl<T> KnownLayout for Unalign<T>
Source§type PointerMetadata = ()
type PointerMetadata = ()
Self
. Read more