Skip to content

Commit

Permalink
Introduce ByteOrder::try_map
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Oct 28, 2023
1 parent ba95ecc commit 8a0b162
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 13 deletions.
26 changes: 20 additions & 6 deletions crates/asm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,20 +142,22 @@ pub mod musli_zerocopy_swap {
pub struct Struct {
bits32: u32,
bits64: u64,
bits128: u128,
array: [u8; 16],
}

#[inline(never)]
pub fn ensure_struct_native(st: Struct) -> Struct {
pub fn ensure_struct_ne(st: Struct) -> Struct {
st.swap_bytes::<endian::Native>()
}

#[inline(never)]
pub fn ensure_struct_little(st: Struct) -> Struct {
pub fn ensure_struct_le(st: Struct) -> Struct {
st.swap_bytes::<endian::Little>()
}

#[inline(never)]
pub fn ensure_struct_big(st: Struct) -> Struct {
pub fn ensure_struct_be(st: Struct) -> Struct {
st.swap_bytes::<endian::Big>()
}

Expand All @@ -167,17 +169,29 @@ pub mod musli_zerocopy_swap {
}

#[inline(never)]
pub fn ensure_enum_native(st: Enum) -> Enum {
pub fn ensure_enum_ne(st: Enum) -> Enum {
st.swap_bytes::<endian::Native>()
}

#[inline(never)]
pub fn ensure_enum_little(st: Enum) -> Enum {
pub fn ensure_enum_le(st: Enum) -> Enum {
st.swap_bytes::<endian::Little>()
}

#[inline(never)]
pub fn ensure_enum_big(st: Enum) -> Enum {
pub fn ensure_enum_be(st: Enum) -> Enum {
st.swap_bytes::<endian::Big>()
}
}

pub mod generic {
pub enum Enum {
Empty,
One(u32),
Two(u32, u64),
}

pub fn do_nothing(en: Enum) -> Enum {
en
}
}
14 changes: 7 additions & 7 deletions crates/musli-macros/src/zero_copy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result<TokenStream, ()> {

swap_bytes_block = quote! {
Self {
#member: <#ty as #zero_copy>::swap_bytes::<#endianness>(self.#member),
#(#ignored_members: self.#ignored_members,)*
#member: <#ty as #zero_copy>::swap_bytes::<#endianness>(this.#member),
#(#ignored_members: this.#ignored_members,)*
}
};
}
Expand Down Expand Up @@ -201,8 +201,8 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result<TokenStream, ()> {

swap_bytes_block = quote! {
Self {
#(#members: <#types as #zero_copy>::swap_bytes::<#endianness>(self.#members),)*
#(#ignored_members: self.#ignored_members,)*
#(#members: <#types as #zero_copy>::swap_bytes::<#endianness>(this.#members),)*
#(#ignored_members: this.#ignored_members,)*
}
};
}
Expand Down Expand Up @@ -397,7 +397,7 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result<TokenStream, ()> {
};

swap_bytes_block = quote! {
match self {
match this {
#(#load_variants),*
}
};
Expand Down Expand Up @@ -454,7 +454,7 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result<TokenStream, ()> {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

let (swap_bytes_block, can_swap_bytes) = if swap_bytes_self {
(quote!(self), quote!(true))
(quote!(this), quote!(true))
} else {
(swap_bytes_block, can_swap_bytes)
};
Expand Down Expand Up @@ -487,7 +487,7 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result<TokenStream, ()> {

#[inline]
fn swap_bytes<#endianness: #byte_order>(self) -> Self {
#swap_bytes_block
<#endianness as #byte_order>::try_map(self, |this| #swap_bytes_block)
}
}
})
Expand Down
29 changes: 29 additions & 0 deletions crates/musli-zerocopy/src/endian/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ mod sealed {
/// [`Little`], and its internals are intentionally hidden. Do not attempt
/// to use them yourself.
pub trait ByteOrder: 'static + Sized + self::sealed::Sealed {
/// Maps the `value` through `map`, unless the current byte order is
/// [`Native`].
#[doc(hidden)]
fn try_map<T, F>(value: T, map: F) -> T where F: FnOnce(T) -> T;

/// Swap the bytes for a `usize` with the current byte order.
#[doc(hidden)]
fn swap_usize(value: usize) -> usize;
Expand Down Expand Up @@ -292,6 +297,18 @@ pub trait ByteOrder: 'static + Sized + self::sealed::Sealed {
}

impl ByteOrder for Little {
#[cfg(target_endian = "little")]
#[inline(always)]
fn try_map<T, F>(value: T, _: F) -> T where F: FnOnce(T) -> T {
value
}

#[cfg(not(target_endian = "little"))]
#[inline(always