diff --git a/crates/asm/src/lib.rs b/crates/asm/src/lib.rs index 5f3c4824d..d84b59e4d 100644 --- a/crates/asm/src/lib.rs +++ b/crates/asm/src/lib.rs @@ -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::() } #[inline(never)] - pub fn ensure_struct_little(st: Struct) -> Struct { + pub fn ensure_struct_le(st: Struct) -> Struct { st.swap_bytes::() } #[inline(never)] - pub fn ensure_struct_big(st: Struct) -> Struct { + pub fn ensure_struct_be(st: Struct) -> Struct { st.swap_bytes::() } @@ -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::() } #[inline(never)] - pub fn ensure_enum_little(st: Enum) -> Enum { + pub fn ensure_enum_le(st: Enum) -> Enum { st.swap_bytes::() } #[inline(never)] - pub fn ensure_enum_big(st: Enum) -> Enum { + pub fn ensure_enum_be(st: Enum) -> Enum { st.swap_bytes::() } } + +pub mod generic { + pub enum Enum { + Empty, + One(u32), + Two(u32, u64), + } + + pub fn do_nothing(en: Enum) -> Enum { + en + } +} diff --git a/crates/musli-macros/src/zero_copy/mod.rs b/crates/musli-macros/src/zero_copy/mod.rs index 2232648bc..ddca3c05d 100644 --- a/crates/musli-macros/src/zero_copy/mod.rs +++ b/crates/musli-macros/src/zero_copy/mod.rs @@ -158,8 +158,8 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result { 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,)* } }; } @@ -201,8 +201,8 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result { 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,)* } }; } @@ -397,7 +397,7 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result { }; swap_bytes_block = quote! { - match self { + match this { #(#load_variants),* } }; @@ -454,7 +454,7 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result { 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) }; @@ -487,7 +487,7 @@ fn expand(cx: &Ctxt, input: syn::DeriveInput) -> Result { #[inline] fn swap_bytes<#endianness: #byte_order>(self) -> Self { - #swap_bytes_block + <#endianness as #byte_order>::try_map(self, |this| #swap_bytes_block) } } }) diff --git a/crates/musli-zerocopy/src/endian/mod.rs b/crates/musli-zerocopy/src/endian/mod.rs index 0568b9da3..9ad11c130 100644 --- a/crates/musli-zerocopy/src/endian/mod.rs +++ b/crates/musli-zerocopy/src/endian/mod.rs @@ -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(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; @@ -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(value: T, _: F) -> T where F: FnOnce(T) -> T { + value + } + + #[cfg(not(target_endian = "little"))] + #[inline(always)] + fn try_map(value: T, map: F) -> T where F: FnOnce(T) -> T { + map(value) + } + #[inline] fn swap_usize(value: usize) -> usize { usize::from_le(value) @@ -354,6 +371,18 @@ impl ByteOrder for Little { } impl ByteOrder for Big { + #[cfg(target_endian = "big")] + #[inline(always)] + fn try_map(value: T, _: F) -> T where F: FnOnce(T) -> T { + value + } + + #[cfg(not(target_endian = "big"))] + #[inline(always)] + fn try_map(value: T, map: F) -> T where F: FnOnce(T) -> T { + map(value) + } + #[inline] fn swap_usize(value: usize) -> usize { usize::from_be(value)