Skip to content

Commit

Permalink
Clean up Endian handling
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Oct 27, 2023
1 parent 83b2db7 commit ed74d9b
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 119 deletions.
20 changes: 10 additions & 10 deletions crates/musli-zerocopy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,9 @@ specify a "sticky" [`ByteOrder`] to use in types which interact with it
during construction:

```rust
use musli_zerocopy::{BigEndian, LittleEndian, Order, OwnedBuf};
use musli_zerocopy::{Big, Little, Order, OwnedBuf};

let mut buf = OwnedBuf::new().with_byte_order::<LittleEndian>();
let mut buf = OwnedBuf::new().with_byte_order::<Little>();

let first = buf.store(&Order::le(42u16));
let portable = Archive {
Expand All @@ -345,7 +345,7 @@ assert_eq!(&buf[..], &[

let portable = buf.load(portable)?;

let mut buf = OwnedBuf::new().with_byte_order::<BigEndian>();
let mut buf = OwnedBuf::new().with_byte_order::<Big>();

let first = buf.store(&Order::be(42u16));
let portable = Archive {
Expand Down Expand Up @@ -406,9 +406,9 @@ The available [`Size`] implementations are:

```rust
// These no longer panic:
let reference = Ref::<Custom, NativeEndian, usize>::new(1usize << 32);
let slice = Ref::<[Custom], NativeEndian, usize>::with_metadata(0, 1usize << 32);
let unsize = Ref::<str, NativeEndian, usize>::with_metadata(0, 1usize << 32);
let reference = Ref::<Custom, Native, usize>::new(1usize << 32);
let slice = Ref::<[Custom], Native, usize>::with_metadata(0, 1usize << 32);
let unsize = Ref::<str, Native, usize>::with_metadata(0, 1usize << 32);
```

To initialize an [`OwnedBuf`] with a custom [`Size`], you can use
Expand All @@ -426,15 +426,15 @@ The [`Size`] you've specified during construction of an [`OwnedBuf`] will
then carry into any pointers it return:

```rust
use musli_zerocopy::{OwnedBuf, Ref, ZeroCopy, NativeEndian};
use musli_zerocopy::{OwnedBuf, Ref, ZeroCopy, Native};
use musli_zerocopy::buf::DefaultAlignment;

#[derive(ZeroCopy)]
#[repr(C)]
struct Custom {
reference: Ref<u32, NativeEndian, usize>,
slice: Ref::<[u32], NativeEndian, usize>,
unsize: Ref::<str, NativeEndian, usize>,
reference: Ref<u32, Native, usize>,
slice: Ref::<[u32], Native, usize>,
unsize: Ref::<str, Native, usize>,
}

let mut buf = OwnedBuf::with_capacity_and_alignment::<DefaultAlignment>(0)
Expand Down
57 changes: 57 additions & 0 deletions crates/musli-zerocopy/examples/dual_archive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//! Example showcasing how to build an archive which contains mixed endian data.

use anyhow::Result;
use musli_zerocopy::endian::{Big, Little};
use musli_zerocopy::{ByteOrder, Endian, OwnedBuf, Ref, ZeroCopy};

#[derive(ZeroCopy)]
#[repr(C)]
struct Header {
big: Ref<Data<Big>, Little>,
little: Ref<Data<Little>, Little>,
}

#[derive(ZeroCopy)]
#[repr(C)]
struct Data<E>
where
E: ByteOrder,
{
name: Ref<str, E>,
age: Endian<u32, E>,
}

fn main() -> Result<()> {
let mut buf = OwnedBuf::new();

let header = buf.store_uninit::<Header>();

// Byte-oriented data has no alignment, so we can re-use the string
// allocation.
let name = buf.store_unsized("John Doe");

let big = buf.store(&Data {
name: name.to_endian(),
age: Endian::new(35),
});

let little = buf.store(&Data {
name: name.to_endian(),
age: Endian::new(35),
});

buf.load_uninit_mut(header).write(&Header { big, little });

buf.align_in_place();

let header = buf.load_at::<Header>(0)?;
let little = buf.load(header.little)?;
let big = buf.load(header.big)?;

dbg!(buf.load(little.name)?);
dbg!(little.age.to_ne(), little.age.to_raw());

dbg!(buf.load(big.name)?);
dbg!(big.age.to_ne(), big.age.to_raw());
Ok(())
}
20 changes: 10 additions & 10 deletions crates/musli-zerocopy/src/buf/owned_buf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::slice::{self, SliceIndex};
use alloc::alloc;

use crate::buf::{Buf, DefaultAlignment, Padder, StoreBuf};
use crate::endian::{ByteOrder, NativeEndian};
use crate::endian::{ByteOrder, Native};
use crate::error::Error;
use crate::mem::MaybeUninit;
use crate::pointer::{DefaultSize, Pointee, Ref, Size};
Expand All @@ -33,7 +33,7 @@ use crate::traits::{UnsizedZeroCopy, ZeroCopy};
/// let mut buf = OwnedBuf::new();
/// buf.store(&Custom { field: 10 });
/// ```
pub struct OwnedBuf<E: ByteOrder = NativeEndian, O: Size = DefaultSize> {
pub struct OwnedBuf<E: ByteOrder = Native, O: Size = DefaultSize> {
data: NonNull<u8>,
/// The initialized length of the buffer.
len: usize,
Expand Down Expand Up @@ -82,10 +82,10 @@ impl OwnedBuf {
/// ```should_panic
/// use std::mem::align_of;
///
/// use musli_zerocopy::{NativeEndian, DefaultAlignment, OwnedBuf};
/// use musli_zerocopy::{endian, DefaultAlignment, OwnedBuf};
///
/// let max = isize::MAX as usize - (align_of::<DefaultAlignment>() - 1);
/// OwnedBuf::<NativeEndian, u32>::with_capacity(max);
/// OwnedBuf::<endian::Native, u32>::with_capacity(max);
/// ```
///
/// # Examples
Expand Down Expand Up @@ -194,10 +194,10 @@ impl<E: ByteOrder, O: Size> OwnedBuf<E, O> {
/// # Examples
///
/// ```
/// use musli_zerocopy::{LittleEndian, OwnedBuf};
/// use musli_zerocopy::{endian, OwnedBuf};
///
/// let mut buf = OwnedBuf::with_capacity(1024)
/// .with_byte_order::<LittleEndian>();
/// .with_byte_order::<endian::Little>();
/// ```
#[inline]
pub fn with_byte_order<U: ByteOrder>(self) -> OwnedBuf<U, O> {
Expand Down Expand Up @@ -919,8 +919,8 @@ impl<E: ByteOrder, O: Size> OwnedBuf<E, O> {
/// if a reallocation is triggered due to reaching its [`capacity()`].
///
/// ```
/// use musli_zerocopy::{NativeEndian, OwnedBuf};
/// let mut buf = OwnedBuf::<NativeEndian, u32>::with_capacity_and_alignment::<u16>(32);
/// use musli_zerocopy::{endian, OwnedBuf};
/// let mut buf = OwnedBuf::<endian::Native, u32>::with_capacity_and_alignment::<u16>(32);
///
/// buf.extend_from_slice(&[1, 2]);
/// assert!(buf.alignment() >= 2);
Expand Down Expand Up @@ -1194,11 +1194,11 @@ impl<E: ByteOrder, O: Size> Borrow<Buf> for OwnedBuf<E, O> {
/// ```
/// use std::mem::align_of;
///
/// use musli_zerocopy::{NativeEndian, OwnedBuf};
/// use musli_zerocopy::{endian, OwnedBuf};
///
/// assert_ne!(align_of::<u16>(), align_of::<u32>());
///
/// let mut buf = OwnedBuf::<NativeEndian, u32>::with_capacity_and_alignment::<u16>(32);
/// let mut buf = OwnedBuf::<endian::Native, u32>::with_capacity_and_alignment::<u16>(32);
/// buf.extend_from_slice(&[1, 2, 3, 4]);
/// buf.request_align::<u32>();
///
Expand Down
8 changes: 4 additions & 4 deletions crates/musli-zerocopy/src/buf/slice_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::slice::{self, SliceIndex};
use alloc::borrow::Cow;

use crate::buf::{Buf, DefaultAlignment, Padder, StoreBuf};
use crate::endian::{ByteOrder, NativeEndian};
use crate::endian::{ByteOrder, Native};
use crate::error::Error;
use crate::mem::MaybeUninit;
use crate::pointer::{DefaultSize, Pointee, Ref, Size};
Expand All @@ -34,7 +34,7 @@ use crate::traits::{UnsizedZeroCopy, ZeroCopy};
/// let mut buf = SliceMut::new(&mut buf);
/// buf.store(&Custom { field: 10 });
/// ```
pub struct SliceMut<'a, E: ByteOrder = NativeEndian, O: Size = DefaultSize> {
pub struct SliceMut<'a, E: ByteOrder = Native, O: Size = DefaultSize> {
/// Base data pointer.
data: NonNull<u8>,
/// The initialized length of the buffer.
Expand Down Expand Up @@ -125,11 +125,11 @@ impl<'a, E: ByteOrder, O: Size> SliceMut<'a, E, O> {
/// # Examples
///
/// ```
/// use musli_zerocopy::{LittleEndian, SliceMut};
/// use musli_zerocopy::{endian, SliceMut};
///
/// let mut buf = [0; 1024];
/// let mut buf = SliceMut::new(&mut buf)
/// .with_byte_order::<LittleEndian>();
/// .with_byte_order::<endian::Little>();
/// ```
#[inline]
pub fn with_byte_order<U: ByteOrder>(self) -> SliceMut<'a, U, O> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
use core::marker::PhantomData;
use core::{any, fmt};

use crate::endian::{BigEndian, ByteOrder, LittleEndian};
use crate::endian::{Big, ByteOrder, Little};
use crate::ZeroCopy;

/// A value capable of enforcing a custom [`ByteOrder`].
/// Wrapper capable of enforcing a custom [`ByteOrder`].
///
/// This can be used to store values in a zero-copy container in a portable
/// manner, which is especially important to transfer types such as `char` which
/// have a limited supported bit-pattern.
#[derive(ZeroCopy)]
#[zero_copy(crate, swap_bytes, bounds = {T: ZeroCopy})]
#[repr(transparent)]
pub struct Order<T, E: ByteOrder> {
pub struct Endian<T, E: ByteOrder> {
value: T,
#[zero_copy(ignore)]
_marker: PhantomData<E>,
}

impl<T: ZeroCopy> Order<T, LittleEndian> {
/// Construct new value wrapper with [`LittleEndian`] [`ByteOrder`].
impl<T: ZeroCopy> Endian<T, Little> {
/// Construct new value wrapper with [`Little`] [`ByteOrder`].
///
/// # Examples
///
/// ```
/// use musli_zerocopy::Order;
/// use musli_zerocopy::Endian;
///
/// let value = Order::le(42u32);
/// let value = Endian::le(42u32);
/// assert_eq!(value.to_ne(), 42);
/// assert_eq!(value.to_raw(), 42u32.to_le());
/// ```
Expand All @@ -36,15 +36,15 @@ impl<T: ZeroCopy> Order<T, LittleEndian> {
}
}

impl<T: ZeroCopy> Order<T, BigEndian> {
/// Construct new value wrapper with [`BigEndian`] [`ByteOrder`].
impl<T: ZeroCopy> Endian<T, Big> {
/// Construct new value wrapper with [`Big`] [`ByteOrder`].
///
/// # Examples
///
/// ```
/// use musli_zerocopy::Order;
/// use musli_zerocopy::Endian;
///
/// let value = Order::be(42u32);
/// let value = Endian::be(42u32);
/// assert_eq!(value.to_ne(), 42);
/// assert_eq!(value.to_raw(), 42u32.to_be());
/// ```
Expand All @@ -54,7 +54,7 @@ impl<T: ZeroCopy> Order<T, BigEndian> {
}
}

impl<T: ZeroCopy, E: ByteOrder> Order<T, E> {
impl<T: ZeroCopy, E: ByteOrder> Endian<T, E> {
/// Construct new value wrapper with the specified [`ByteOrder`].
///
/// # Panics
Expand All @@ -63,18 +63,18 @@ impl<T: ZeroCopy, E: ByteOrder> Order<T, E> {
/// byte-ordered.
///
/// ```should_panic
/// use musli_zerocopy::{LittleEndian, Order};
/// use musli_zerocopy::{endian, Endian};
///
/// let _: Order<_, LittleEndian> = Order::new('a');
/// let _: Endian<_, endian::Little> = Endian::new('a');
/// ```
///
/// # Examples
///
/// ```
/// use musli_zerocopy::{BigEndian, LittleEndian, Order, ZeroCopy};
/// use musli_zerocopy::{endian, Endian, ZeroCopy};
///
/// let mut a: Order<_, BigEndian> = Order::new('a' as u32);
/// let mut b: Order<_, LittleEndian> = Order::new('a' as u32);
/// let mut a: Endian<_, endian::Big> = Endian::new('a' as u32);
/// let mut b: Endian<_, endian::Little> = Endian::new('a' as u32);
///
/// assert_eq!(a.to_ne(), 'a' as u32);
/// assert_eq!(a.to_bytes(), &[0, 0, 0, 97]);
Expand All @@ -101,9 +101,9 @@ impl<T: ZeroCopy, E: ByteOrder> Order<T, E> {
/// # Examples
///
/// ```
/// use musli_zerocopy::Order;
/// use musli_zerocopy::Endian;
///
/// let value = Order::le(42u32);
/// let value = Endian::le(42u32);
/// assert_eq!(value.to_ne(), 42);
/// assert_eq!(value.to_raw(), 42u32.to_le());
/// ```
Expand All @@ -117,9 +117,9 @@ impl<T: ZeroCopy, E: ByteOrder> Order<T, E> {
/// # Examples
///
/// ```
/// use musli_zerocopy::Order;
/// use musli_zerocopy::Endian;
///
/// let value = Order::le(42u32);
/// let value = Endian::le(42u32);
/// assert_eq!(value.to_ne(), 42);
/// assert_eq!(value.to_raw(), 42u32.to_le());
/// ```
Expand All @@ -129,20 +129,18 @@ impl<T: ZeroCopy, E: ByteOrder> Order<T, E> {
}
}

impl<T, E> fmt::Debug for Order<T, E>
impl<T, E> fmt::Debug for Endian<T, E>
where
T: fmt::Debug + ZeroCopy,
E: ByteOrder,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Order")
.field("value", &self.value)
.field("_marker", &self._marker)
.finish()
write!(f, "Endian<{}>({:?})", any::type_name::<E>(), self.value)
}
}

impl<T, E> Clone for Order<T, E>
impl<T, E> Clone for Endian<T, E>
where
T: Clone + ZeroCopy,
E: ByteOrder,
Expand All @@ -155,7 +153,7 @@ where
}
}

impl<T, E> Copy for Order<T, E>
impl<T, E> Copy for Endian<T, E>
where
T: Copy + ZeroCopy,
E: ByteOrder,
Expand Down
Loading

0 comments on commit ed74d9b

Please sign in to comment.