diff options
| -rw-r--r-- | crates/core_simd/src/lib.rs | 3 | ||||
| -rw-r--r-- | crates/core_simd/src/to_bytes.rs | 68 | ||||
| -rw-r--r-- | crates/core_simd/tests/to_bytes.rs | 10 |
3 files changed, 81 insertions, 0 deletions
diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 3489dfb5f3e..0a16b5dacf0 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -17,6 +17,9 @@ mod reduction; mod select; pub use select::Select; +mod to_bytes; +pub use to_bytes::ToBytes; + mod comparisons; mod fmt; mod intrinsics; diff --git a/crates/core_simd/src/to_bytes.rs b/crates/core_simd/src/to_bytes.rs new file mode 100644 index 00000000000..a2d9cc4ef56 --- /dev/null +++ b/crates/core_simd/src/to_bytes.rs @@ -0,0 +1,68 @@ +mod sealed { + pub trait Sealed {} +} +use sealed::Sealed; + +/// Supporting trait for byte conversion functions. +pub trait ToBytes: Sealed { + /// The bytes representation of this type. + type Bytes; + + #[doc(hidden)] + fn to_bytes_impl(self) -> Self::Bytes; + + #[doc(hidden)] + fn from_bytes_impl(bytes: Self::Bytes) -> Self; +} + +macro_rules! impl_to_bytes { + { $name:ident, $($int_width:literal -> $byte_width:literal),* } => { + $( + impl Sealed for crate::$name<$int_width> where Self: crate::LanesAtMost32 {} + impl ToBytes for crate::$name<$int_width> + where + Self: crate::LanesAtMost32, + crate::SimdU8<$byte_width>: crate::LanesAtMost32, + { + type Bytes = crate::SimdU8<$byte_width>; + fn to_bytes_impl(self) -> Self::Bytes { + unsafe { core::mem::transmute(self) } + } + fn from_bytes_impl(bytes: Self::Bytes) -> Self { + unsafe { core::mem::transmute(bytes) } + } + } + )* + + impl<const LANES: usize> crate::$name<LANES> + where + Self: ToBytes + crate::LanesAtMost32, + { + /// Return the memory representation of this integer as a byte array in native byte + /// order. + pub fn to_ne_bytes(self) -> <Self as ToBytes>::Bytes { self.to_bytes_impl() } + + /// Create a native endian integer value from its memory representation as a byte array + /// in native endianness. + pub fn from_ne_bytes(bytes: <Self as ToBytes>::Bytes) -> Self { Self::from_bytes_impl(bytes) } + } + } +} + +impl_to_bytes! { SimdU8, 1 -> 1, 2 -> 2, 4 -> 4, 8 -> 8, 16 -> 16, 32 -> 32 } +impl_to_bytes! { SimdU16, 1 -> 2, 2 -> 4, 4 -> 8, 8 -> 16, 16 -> 32 } +impl_to_bytes! { SimdU32, 1 -> 4, 2 -> 8, 4 -> 16, 8 -> 32 } +impl_to_bytes! { SimdU64, 1 -> 8, 2 -> 16, 4 -> 32 } +#[cfg(target_pointer_width = "32")] +impl_to_bytes! { SimdUsize, 1 -> 4, 2 -> 8, 4 -> 16, 8 -> 32 } +#[cfg(target_pointer_width = "64")] +impl_to_bytes! { SimdUsize, 1 -> 8, 2 -> 16, 4 -> 32 } + +impl_to_bytes! { SimdI8, 1 -> 1, 2 -> 2, 4 -> 4, 8 -> 8, 16 -> 16, 32 -> 32 } +impl_to_bytes! { SimdI16, 1 -> 2, 2 -> 4, 4 -> 8, 8 -> 16, 16 -> 32 } +impl_to_bytes! { SimdI32, 1 -> 4, 2 -> 8, 4 -> 16, 8 -> 32 } +impl_to_bytes! { SimdI64, 1 -> 8, 2 -> 16, 4 -> 32 } +#[cfg(target_pointer_width = "32")] +impl_to_bytes! { SimdIsize, 1 -> 4, 2 -> 8, 4 -> 16, 8 -> 32 } +#[cfg(target_pointer_width = "64")] +impl_to_bytes! { SimdIsize, 1 -> 8, 2 -> 16, 4 -> 32 } diff --git a/crates/core_simd/tests/to_bytes.rs b/crates/core_simd/tests/to_bytes.rs new file mode 100644 index 00000000000..20da1652a6d --- /dev/null +++ b/crates/core_simd/tests/to_bytes.rs @@ -0,0 +1,10 @@ +use core_simd::SimdU32; + +#[test] +fn byte_convert() { + let int = SimdU32::from_array([0xdeadbeef, 0x8badf00d]); + let bytes = int.to_ne_bytes(); + assert_eq!(int[0].to_ne_bytes(), bytes[..4]); + assert_eq!(int[1].to_ne_bytes(), bytes[4..]); + assert_eq!(SimdU32::from_ne_bytes(bytes), int); +} |
