Skip to content

Commit 4f5e901

Browse files
joshlfCQ Bot
authored andcommitted
[zerocopy] Add Unalign, read/write methods
Add `Unalign`, which wraps a type and removes any alignment requirement, allowing it to be safely read from any location in memory regardless of alignment. Add `FromBytes` constructors `read`, `read_from_prefix`, and `read_from_suffix`, which read an instance of a `FromBytes` type from a byte slice. Add `AsBytes` methods `write`, `write_to_prefix`, and `write_to_suffix`, which write a copy of `self` to a byte slices. Add `LayoutVerified::<_, T>::read`, which reads a `T` from the underlying bytes. Add `LayoutVerified::<_, T>::write`, which writes a `T` to the underlying bytes. Release zerocopy version 0.6.0. Change-Id: Ibeff90a8f950b832178eecc550b42ecfc98d79f2 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/570485 Commit-Queue: Joshua Liebow-Feeser <[email protected]> Reviewed-by: Tyler Mandry <[email protected]> Reviewed-by: Adam Perry <[email protected]> Reviewed-by: Manish Goregaokar <[email protected]>
1 parent cfb2a95 commit 4f5e901

File tree

2 files changed

+258
-4
lines changed

2 files changed

+258
-4
lines changed

Cargo.toml.crates-io

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[package]
88
edition = "2018"
99
name = "zerocopy"
10-
version = "0.5.1"
10+
version = "0.6.0"
1111
authors = ["Joshua Liebow-Feeser <[email protected]>"]
1212
description = "Utilities for zero-copy parsing and serialization"
1313
license = "BSD-3-Clause"

src/lib.rs

Lines changed: 257 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ use core::fmt::{self, Debug, Display, Formatter};
5656
use core::marker::PhantomData;
5757
use core::mem;
5858
use core::ops::{Deref, DerefMut};
59+
use core::ptr;
5960
use core::slice;
6061

6162
// This is a hack to allow derives of FromBytes, AsBytes, and Unaligned to work
@@ -186,6 +187,43 @@ pub unsafe trait FromBytes {
186187
where
187188
Self: Sized;
188189

190+
/// Reads a copy of `Self` from `bytes`.
191+
///
192+
/// If `bytes.len() != size_of::<Self>()`, `read_from` returns `None`.
193+
fn read_from<B: ByteSlice>(bytes: B) -> Option<Self>
194+
where
195+
Self: Sized,
196+
{
197+
let lv = LayoutVerified::<_, Unalign<Self>>::new_unaligned(bytes)?;
198+
Some(lv.read().into_inner())
199+
}
200+
201+
/// Reads a copy of `Self` from the prefix of `bytes`.
202+
///
203+
/// `read_from_prefix` reads a `Self` from the first `size_of::<Self>()`
204+
/// bytes of `bytes`. If `bytes.len() < size_of::<Self>()`, it returns
205+
/// `None`.
206+
fn read_from_prefix<B: ByteSlice>(bytes: B) -> Option<Self>
207+
where
208+
Self: Sized,
209+
{
210+
let (lv, _suffix) = LayoutVerified::<_, Unalign<Self>>::new_unaligned_from_prefix(bytes)?;
211+
Some(lv.read().into_inner())
212+
}
213+
214+
/// Reads a copy of `Self` from the suffix of `bytes`.
215+
///
216+
/// `read_from_suffix` reads a `Self` from the last `size_of::<Self>()`
217+
/// bytes of `bytes`. If `bytes.len() < size_of::<Self>()`, it returns
218+
/// `None`.
219+
fn read_from_suffix<B: ByteSlice>(bytes: B) -> Option<Self>
220+
where
221+
Self: Sized,
222+
{
223+
let (_prefix, lv) = LayoutVerified::<_, Unalign<Self>>::new_unaligned_from_suffix(bytes)?;
224+
Some(lv.read().into_inner())
225+
}
226+
189227
/// Creates an instance of `Self` from zeroed bytes.
190228
fn new_zeroed() -> Self
191229
where
@@ -379,6 +417,42 @@ pub unsafe trait AsBytes {
379417
slice::from_raw_parts_mut(self as *mut Self as *mut u8, len)
380418
}
381419
}
420+
421+
/// Writes a copy of `self` to `bytes`.
422+
///
423+
/// If `bytes.len() != size_of_val(self)`, `write_to` returns `None`.
424+
fn write_to<B: ByteSliceMut>(&self, mut bytes: B) -> Option<()> {
425+
if bytes.len() != mem::size_of_val(self) {
426+
return None;
427+
}
428+
429+
bytes.copy_from_slice(self.as_bytes());
430+
Some(())
431+
}
432+
433+
/// Writes a copy of `self` to the prefix of `bytes`.
434+
///
435+
/// `write_to_prefix` writes `self` to the first `size_of_val(self)` bytes
436+
/// of `bytes`. If `bytes.len() < size_of_val(self)`, it returns `None`.
437+
fn write_to_prefix<B: ByteSliceMut>(&self, mut bytes: B) -> Option<()> {
438+
let size = mem::size_of_val(self);
439+
if bytes.len() < size {
440+
return None;
441+
}
442+
443+
bytes[..size].copy_from_slice(self.as_bytes());
444+
Some(())
445+
}
446+
447+
/// Writes a copy of `self` to the suffix of `bytes`.
448+
///
449+
/// `write_to_suffix` writes `self` to the last `size_of_val(self)` bytes
450+
/// of `bytes`. If `bytes.len() < size_of_val(self)`, it returns `None`.
451+
fn write_to_suffix<B: ByteSliceMut>(&self, mut bytes: B) -> Option<()> {
452+
let start = bytes.len().checked_sub(mem::size_of_val(self))?;
453+
bytes[start..].copy_from_slice(self.as_bytes());
454+
Some(())
455+
}
382456
}
383457

384458
// Special case for bool (it is not included in `impl_for_primitives!`).
@@ -543,6 +617,103 @@ mod simd {
543617
);
544618
}
545619

620+
/// A type with no alignment requirement.
621+
///
622+
/// A `Unalign` wraps a `T`, removing any alignment requirement. `Unalign<T>`
623+
/// has the same size and ABI as `T`, but not necessarily the same alignment.
624+
/// This is useful if a type with an alignment requirement needs to be read from
625+
/// a chunk of memory which provides no alignment guarantees.
626+
///
627+
/// Since `Unalign` has no alignment requirement, the inner `T` may not be
628+
/// properly aligned in memory, and so `Unalign` provides no way of getting a
629+
/// reference to the inner `T`. Instead, the `T` may only be obtained by value
630+
/// (see [`get`] and [`into_inner`]).
631+
///
632+
/// [`get`]: Unalign::get
633+
/// [`into_inner`]: Unalign::into_inner
634+
#[derive(FromBytes, Unaligned, Copy)]
635+
#[repr(C, packed)]
636+
pub struct Unalign<T>(T);
637+
638+
// Note that `Unalign: Clone` only if `T: Copy`. Since the inner `T` may not be
639+
// aligned, there's no way to safely call `T::clone`, and so a `T: Clone` bound
640+
// is not sufficient to implement `Clone` for `Unalign`.
641+
impl<T: Copy> Clone for Unalign<T> {
642+
fn clone(&self) -> Unalign<T> {
643+
*self
644+
}
645+
}
646+
647+
impl<T> Unalign<T> {
648+
/// Constructs a new `Unalign`.
649+
pub fn new(val: T) -> Unalign<T> {
650+
Unalign(val)
651+
}
652+
653+
/// Consumes `self`, returning the inner `T`.
654+
pub fn into_inner(self) -> T {
655+
let Unalign(val) = self;
656+
val
657+
}
658+
659+
/// Gets an unaligned raw pointer to the inner `T`.
660+
///
661+
/// # Safety
662+
///
663+
/// The returned raw pointer is not necessarily aligned to
664+
/// `align_of::<T>()`. Most functions which operate on raw pointers require
665+
/// those pointers to be aligned, so calling those functions with the result
666+
/// of `get_ptr` will be undefined behavior if alignment is not guaranteed
667+
/// using some out-of-band mechanism. In general, the only functions which
668+
/// are safe to call with this pointer are which that are explicitly
669+
/// documented as being sound to use with an unaligned pointer, such as
670+
/// [`read_unaligned`].
671+
///
672+
/// [`read_unaligned`]: core::ptr::read_unaligned
673+
pub fn get_ptr(&self) -> *const T {
674+
ptr::addr_of!(self.0)
675+
}
676+
677+
/// Gets an unaligned mutable raw pointer to the inner `T`.
678+
///
679+
/// # Safety
680+
///
681+
/// The returned raw pointer is not necessarily aligned to
682+
/// `align_of::<T>()`. Most functions which operate on raw pointers require
683+
/// those pointers to be aligned, so calling those functions with the result
684+
/// of `get_ptr` will be undefined behavior if alignment is not guaranteed
685+
/// using some out-of-band mechanism. In general, the only functions which
686+
/// are safe to call with this pointer are those which are explicitly
687+
/// documented as being sound to use with an unaligned pointer, such as
688+
/// [`read_unaligned`].
689+
///
690+
/// [`read_unaligned`]: core::ptr::read_unaligned
691+
pub fn get_mut_ptr(&mut self) -> *mut T {
692+
ptr::addr_of_mut!(self.0)
693+
}
694+
}
695+
696+
impl<T: Copy> Unalign<T> {
697+
/// Gets a copy of the inner `T`.
698+
pub fn get(&self) -> T {
699+
let Unalign(val) = *self;
700+
val
701+
}
702+
}
703+
704+
// SAFETY: Since `T: AsBytes`, we know that it's safe to construct a `&[u8]`
705+
// from an aligned `&T`. Since `&[u8]` itself has no alignment requirements, it
706+
// must also be safe to construct a `&[u8]` from a `&T` at any address. Since
707+
// `Unalign<T>` is `#[repr(packed)]`, everything about its layout except for its
708+
// alignment is the same as `T`'s layout.
709+
unsafe impl<T: AsBytes> AsBytes for Unalign<T> {
710+
fn only_derive_is_allowed_to_implement_this_trait()
711+
where
712+
Self: Sized,
713+
{
714+
}
715+
}
716+
546717
// Used in `transmute!` below.
547718
#[doc(hidden)]
548719
pub use core::mem::transmute as __real_transmute;
@@ -1397,6 +1568,39 @@ where
13971568
}
13981569
}
13991570

1571+
impl<B, T> LayoutVerified<B, T>
1572+
where
1573+
B: ByteSlice,
1574+
T: FromBytes,
1575+
{
1576+
/// Reads a copy of `T`.
1577+
#[inline]
1578+
pub fn read(&self) -> T {
1579+
// SAFETY: Because of the invariants on `LayoutVerified`, we know that
1580+
// `self.0` is at least `size_of::<T>()` bytes long, and that it is at
1581+
// least as aligned as `align_of::<T>()`. Because `T: FromBytes`, it is
1582+
// sound to interpret these bytes as a `T`.
1583+
unsafe { ptr::read(self.0.as_ptr() as *const T) }
1584+
}
1585+
}
1586+
1587+
impl<B, T> LayoutVerified<B, T>
1588+
where
1589+
B: ByteSliceMut,
1590+
T: AsBytes,
1591+
{
1592+
/// Writes the bytes of `t` and then forgets `t`.
1593+
#[inline]
1594+
pub fn write(&mut self, t: T) {
1595+
// SAFETY: Because of the invariants on `LayoutVerified`, we know that
1596+
// `self.0` is at least `size_of::<T>()` bytes long, and that it is at
1597+
// least as aligned as `align_of::<T>()`. Writing `t` to the buffer will
1598+
// allow all of the bytes of `t` to be accessed as a `[u8]`, but because
1599+
// `T: AsBytes`, we know this is sound.
1600+
unsafe { ptr::write(self.0.as_mut_ptr() as *mut T, t) }
1601+
}
1602+
}
1603+
14001604
impl<B, T> Deref for LayoutVerified<B, T>
14011605
where
14021606
B: ByteSlice,
@@ -1760,7 +1964,6 @@ mod tests {
17601964
#![allow(clippy::unreadable_literal)]
17611965

17621966
use core::ops::Deref;
1763-
use core::ptr;
17641967

17651968
use super::*;
17661969

@@ -1783,6 +1986,43 @@ mod tests {
17831986
unsafe { ptr::read(&u as *const u64 as *const [u8; 8]) }
17841987
}
17851988

1989+
#[test]
1990+
fn test_read_write() {
1991+
const VAL: u64 = 0x12345678;
1992+
#[cfg(target_endian = "big")]
1993+
const VAL_BYTES: [u8; 8] = VAL.to_be_bytes();
1994+
#[cfg(target_endian = "little")]
1995+
const VAL_BYTES: [u8; 8] = VAL.to_le_bytes();
1996+
1997+
// Test FromBytes::{read_from, read_from_prefix, read_from_suffix}
1998+
1999+
assert_eq!(u64::read_from(&VAL_BYTES[..]), Some(VAL));
2000+
// The first 8 bytes are from `VAL_BYTES` and the second 8 bytes are all
2001+
// zeroes.
2002+
let bytes_with_prefix: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]);
2003+
assert_eq!(u64::read_from_prefix(&bytes_with_prefix[..]), Some(VAL));
2004+
assert_eq!(u64::read_from_suffix(&bytes_with_prefix[..]), Some(0));
2005+
// The first 8 bytes are all zeroes and the second 8 bytes are from
2006+
// `VAL_BYTES`
2007+
let bytes_with_suffix: [u8; 16] = transmute!([[0; 8], VAL_BYTES]);
2008+
assert_eq!(u64::read_from_prefix(&bytes_with_suffix[..]), Some(0));
2009+
assert_eq!(u64::read_from_suffix(&bytes_with_suffix[..]), Some(VAL));
2010+
2011+
// Test AsBytes::{write_to, write_to_prefix, write_to_suffix}
2012+
2013+
let mut bytes = [0u8; 8];
2014+
assert_eq!(VAL.write_to(&mut bytes[..]), Some(()));
2015+
assert_eq!(bytes, VAL_BYTES);
2016+
let mut bytes = [0u8; 16];
2017+
assert_eq!(VAL.write_to_prefix(&mut bytes[..]), Some(()));
2018+
let want: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]);
2019+
assert_eq!(bytes, want);
2020+
let mut bytes = [0u8; 16];
2021+
assert_eq!(VAL.write_to_suffix(&mut bytes[..]), Some(()));
2022+
let want: [u8; 16] = transmute!([[0; 8], VAL_BYTES]);
2023+
assert_eq!(bytes, want);
2024+
}
2025+
17862026
#[test]
17872027
fn test_transmute() {
17882028
// Test that memory is transmuted as expected.
@@ -1825,22 +2065,29 @@ mod tests {
18252065
}
18262066

18272067
// verify that values written to a LayoutVerified are properly shared
1828-
// between the typed and untyped representations
2068+
// between the typed and untyped representations, that reads via `deref` and
2069+
// `read` behave the same, and that writes via `deref_mut` and `write`
2070+
// behave the same
18292071
fn test_new_helper<'a>(mut lv: LayoutVerified<&'a mut [u8], u64>) {
18302072
// assert that the value starts at 0
18312073
assert_eq!(*lv, 0);
2074+
assert_eq!(lv.read(), 0);
18322075

18332076
// assert that values written to the typed value are reflected in the
18342077
// byte slice
18352078
const VAL1: u64 = 0xFF00FF00FF00FF00;
18362079
*lv = VAL1;
18372080
assert_eq!(lv.bytes(), &u64_to_bytes(VAL1));
2081+
*lv = 0;
2082+
lv.write(VAL1);
2083+
assert_eq!(lv.bytes(), &u64_to_bytes(VAL1));
18382084

18392085
// assert that values written to the byte slice are reflected in the
18402086
// typed value
18412087
const VAL2: u64 = !VAL1; // different from VAL1
18422088
lv.bytes_mut().copy_from_slice(&u64_to_bytes(VAL2)[..]);
18432089
assert_eq!(*lv, VAL2);
2090+
assert_eq!(lv.read(), VAL2);
18442091
}
18452092

18462093
// verify that values written to a LayoutVerified are properly shared
@@ -1871,22 +2118,29 @@ mod tests {
18712118
}
18722119

18732120
// verify that values written to a LayoutVerified are properly shared
1874-
// between the typed and untyped representations
2121+
// between the typed and untyped representations, that reads via `deref` and
2122+
// `read` behave the same, and that writes via `deref_mut` and `write`
2123+
// behave the same
18752124
fn test_new_helper_unaligned<'a>(mut lv: LayoutVerified<&'a mut [u8], [u8; 8]>) {
18762125
// assert that the value starts at 0
18772126
assert_eq!(*lv, [0; 8]);
2127+
assert_eq!(lv.read(), [0; 8]);
18782128

18792129
// assert that values written to the typed value are reflected in the
18802130
// byte slice
18812131
const VAL1: [u8; 8] = [0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00];
18822132
*lv = VAL1;
18832133
assert_eq!(lv.bytes(), &VAL1);
2134+
*lv = [0; 8];
2135+
lv.write(VAL1);
2136+
assert_eq!(lv.bytes(), &VAL1);
18842137

18852138
// assert that values written to the byte slice are reflected in the
18862139
// typed value
18872140
const VAL2: [u8; 8] = [0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF]; // different from VAL1
18882141
lv.bytes_mut().copy_from_slice(&VAL2[..]);
18892142
assert_eq!(*lv, VAL2);
2143+
assert_eq!(lv.read(), VAL2);
18902144
}
18912145

18922146
// verify that values written to a LayoutVerified are properly shared

0 commit comments

Comments
 (0)