1use crate::simd::{
2 Simd,
3 num::{SimdFloat, SimdInt, SimdUint},
4};
5
6pub impl(self) trait ToBytes {
8 type Bytes: Copy
10 + Unpin
11 + Send
12 + Sync
13 + AsRef<[u8]>
14 + AsMut<[u8]>
15 + SimdUint<Scalar = u8>
16 + 'static;
17
18 fn to_ne_bytes(self) -> Self::Bytes;
21
22 fn to_be_bytes(self) -> Self::Bytes;
25
26 fn to_le_bytes(self) -> Self::Bytes;
29
30 fn from_ne_bytes(bytes: Self::Bytes) -> Self;
33
34 fn from_be_bytes(bytes: Self::Bytes) -> Self;
36
37 fn from_le_bytes(bytes: Self::Bytes) -> Self;
39}
40
41macro_rules! swap_bytes {
42 { f32, $x:expr } => { Simd::from_bits($x.to_bits().swap_bytes()) };
43 { f64, $x:expr } => { Simd::from_bits($x.to_bits().swap_bytes()) };
44 { $ty:ty, $x:expr } => { $x.swap_bytes() }
45}
46
47macro_rules! impl_to_bytes {
48 { $ty:tt, 1 } => { impl_to_bytes! { $ty, 1 * [1, 2, 4, 8, 16, 32, 64] } };
49 { $ty:tt, 2 } => { impl_to_bytes! { $ty, 2 * [1, 2, 4, 8, 16, 32] } };
50 { $ty:tt, 4 } => { impl_to_bytes! { $ty, 4 * [1, 2, 4, 8, 16] } };
51 { $ty:tt, 8 } => { impl_to_bytes! { $ty, 8 * [1, 2, 4, 8] } };
52 { $ty:tt, 16 } => { impl_to_bytes! { $ty, 16 * [1, 2, 4] } };
53 { $ty:tt, 32 } => { impl_to_bytes! { $ty, 32 * [1, 2] } };
54 { $ty:tt, 64 } => { impl_to_bytes! { $ty, 64 * [1] } };
55
56 { $ty:tt, $size:literal * [$($elems:literal),*] } => {
57 $(
58 impl ToBytes for Simd<$ty, $elems> {
59 type Bytes = Simd<u8, { $size * $elems }>;
60
61 #[inline]
62 fn to_ne_bytes(self) -> Self::Bytes {
63 unsafe {
65 #![allow(clippy::useless_transmute)]
66 core::mem::transmute(self)
67 }
68 }
69
70 #[inline]
71 fn to_be_bytes(mut self) -> Self::Bytes {
72 if !cfg!(target_endian = "big") {
73 self = swap_bytes!($ty, self);
74 }
75 self.to_ne_bytes()
76 }
77
78 #[inline]
79 fn to_le_bytes(mut self) -> Self::Bytes {
80 if !cfg!(target_endian = "little") {
81 self = swap_bytes!($ty, self);
82 }
83 self.to_ne_bytes()
84 }
85
86 #[inline]
87 fn from_ne_bytes(bytes: Self::Bytes) -> Self {
88 unsafe {
90 #![allow(clippy::useless_transmute)]
91 core::mem::transmute(bytes)
92 }
93 }
94
95 #[inline]
96 fn from_be_bytes(bytes: Self::Bytes) -> Self {
97 let ret = Self::from_ne_bytes(bytes);
98 if cfg!(target_endian = "big") {
99 ret
100 } else {
101 swap_bytes!($ty, ret)
102 }
103 }
104
105 #[inline]
106 fn from_le_bytes(bytes: Self::Bytes) -> Self {
107 let ret = Self::from_ne_bytes(bytes);
108 if cfg!(target_endian = "little") {
109 ret
110 } else {
111 swap_bytes!($ty, ret)
112 }
113 }
114 }
115 )*
116 }
117}
118
119impl_to_bytes! { u8, 1 }
120impl_to_bytes! { u16, 2 }
121impl_to_bytes! { u32, 4 }
122impl_to_bytes! { u64, 8 }
123#[cfg(target_pointer_width = "32")]
124impl_to_bytes! { usize, 4 }
125#[cfg(target_pointer_width = "64")]
126impl_to_bytes! { usize, 8 }
127
128impl_to_bytes! { i8, 1 }
129impl_to_bytes! { i16, 2 }
130impl_to_bytes! { i32, 4 }
131impl_to_bytes! { i64, 8 }
132#[cfg(target_pointer_width = "32")]
133impl_to_bytes! { isize, 4 }
134#[cfg(target_pointer_width = "64")]
135impl_to_bytes! { isize, 8 }
136
137impl_to_bytes! { f32, 4 }
138impl_to_bytes! { f64, 8 }