1#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
20pub enum EndianType {
21 #[default]
23 NativeEndian,
24 LittleEndian,
29 BigEndian,
34}
35
36impl EndianType {
37 pub const fn is_le(&self) -> bool {
38 #[cfg(target_endian = "little")]
39 {
40 matches!(self, Self::LittleEndian | Self::NativeEndian)
41 }
42 #[cfg(target_endian = "big")]
43 {
44 matches!(self, Self::LittleEndian)
45 }
46 }
47 pub fn read_u16(&self, bytes: [u8; 2]) -> u16 {
49 match self {
50 EndianType::NativeEndian => u16::from_ne_bytes(bytes),
51 EndianType::LittleEndian => u16::from_le_bytes(bytes),
52 EndianType::BigEndian => u16::from_be_bytes(bytes),
53 }
54 }
55
56 pub fn read_u32(&self, bytes: [u8; 4]) -> u32 {
58 match self {
59 EndianType::NativeEndian => u32::from_ne_bytes(bytes),
60 EndianType::LittleEndian => u32::from_le_bytes(bytes),
61 EndianType::BigEndian => u32::from_be_bytes(bytes),
62 }
63 }
64
65 pub fn read_u64(&self, bytes: [u8; 8]) -> u64 {
67 match self {
68 EndianType::NativeEndian => u64::from_ne_bytes(bytes),
69 EndianType::LittleEndian => u64::from_le_bytes(bytes),
70 EndianType::BigEndian => u64::from_be_bytes(bytes),
71 }
72 }
73
74 pub fn u16_bytes(&self, value: u16) -> [u8; 2] {
76 match self {
77 EndianType::NativeEndian => value.to_ne_bytes(),
78 EndianType::LittleEndian => value.to_le_bytes(),
79 EndianType::BigEndian => value.to_be_bytes(),
80 }
81 }
82
83 pub fn u32_bytes(&self, value: u32) -> [u8; 4] {
85 match self {
86 EndianType::NativeEndian => value.to_ne_bytes(),
87 EndianType::LittleEndian => value.to_le_bytes(),
88 EndianType::BigEndian => value.to_be_bytes(),
89 }
90 }
91
92 pub fn u64_bytes(&self, value: u64) -> [u8; 8] {
94 match self {
95 EndianType::NativeEndian => value.to_ne_bytes(),
96 EndianType::LittleEndian => value.to_le_bytes(),
97 EndianType::BigEndian => value.to_be_bytes(),
98 }
99 }
100}
101
102pub trait Endianness: Copy + Sized {
107 fn get() -> EndianType;
109
110 fn get_u16(bytes: [u8; 2]) -> u16;
112 fn set_u16(value: u16, bytes: &mut [u8; 2]);
114 fn get_u32(bytes: [u8; 4]) -> u32;
116 fn set_u32(value: u32, bytes: &mut [u8; 4]);
118 fn get_u64(bytes: [u8; 8]) -> u64;
120 fn set_u64(value: u64, bytes: &mut [u8; 8]);
122}
123
124#[repr(transparent)]
128#[derive(Debug, Copy, Clone)]
129#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
130pub struct NativeEndian;
131
132#[repr(transparent)]
136#[derive(Debug, Copy, Clone)]
137#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
138pub struct LittleEndian;
139
140#[repr(transparent)]
144#[derive(Debug, Copy, Clone)]
145#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
146pub struct BigEndian;
147
148impl Endianness for NativeEndian {
149 #[inline]
150 fn get() -> EndianType {
151 EndianType::NativeEndian
152 }
153
154 #[inline]
155 fn get_u16(bytes: [u8; 2]) -> u16 {
156 u16::from_ne_bytes(bytes)
157 }
158
159 #[inline]
160 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
161 bytes.copy_from_slice(&value.to_ne_bytes());
162 }
163
164 #[inline]
165 fn get_u32(bytes: [u8; 4]) -> u32 {
166 u32::from_ne_bytes(bytes)
167 }
168
169 #[inline]
170 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
171 bytes.copy_from_slice(&value.to_ne_bytes());
172 }
173
174 #[inline]
175 fn get_u64(bytes: [u8; 8]) -> u64 {
176 u64::from_ne_bytes(bytes)
177 }
178
179 #[inline]
180 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
181 bytes.copy_from_slice(&value.to_ne_bytes());
182 }
183}
184
185impl Endianness for LittleEndian {
186 #[inline]
187 fn get() -> EndianType {
188 EndianType::LittleEndian
189 }
190
191 #[inline]
192 fn get_u16(bytes: [u8; 2]) -> u16 {
193 u16::from_le_bytes(bytes)
194 }
195
196 #[inline]
197 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
198 bytes.copy_from_slice(&value.to_le_bytes());
199 }
200
201 #[inline]
202 fn get_u32(bytes: [u8; 4]) -> u32 {
203 u32::from_le_bytes(bytes)
204 }
205
206 #[inline]
207 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
208 bytes.copy_from_slice(&value.to_le_bytes());
209 }
210
211 #[inline]
212 fn get_u64(bytes: [u8; 8]) -> u64 {
213 u64::from_le_bytes(bytes)
214 }
215
216 #[inline]
217 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
218 bytes.copy_from_slice(&value.to_le_bytes());
219 }
220}
221impl Endianness for BigEndian {
222 #[inline]
223 fn get() -> EndianType {
224 EndianType::BigEndian
225 }
226
227 #[inline]
228 fn get_u16(bytes: [u8; 2]) -> u16 {
229 u16::from_be_bytes(bytes)
230 }
231
232 #[inline]
233 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
234 bytes.copy_from_slice(&value.to_be_bytes());
235 }
236
237 #[inline]
238 fn get_u32(bytes: [u8; 4]) -> u32 {
239 u32::from_be_bytes(bytes)
240 }
241
242 #[inline]
243 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
244 bytes.copy_from_slice(&value.to_be_bytes());
245 }
246
247 #[inline]
248 fn get_u64(bytes: [u8; 8]) -> u64 {
249 u64::from_be_bytes(bytes)
250 }
251
252 #[inline]
253 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
254 bytes.copy_from_slice(&value.to_be_bytes());
255 }
256}
257
258#[cfg(feature = "bytemuck")]
261pub trait MaybePod: bytemuck::Pod + bytemuck::Zeroable {}
262#[cfg(feature = "bytemuck")]
263impl<T: bytemuck::Pod + bytemuck::Zeroable> MaybePod for T {}
264#[cfg(not(feature = "bytemuck"))]
265pub trait MaybePod {}
266#[cfg(not(feature = "bytemuck"))]
267impl<T> MaybePod for T {}
268
269pub trait Endian {
282 type Output: MaybePod;
289
290 type LsbType: MaybePod + Endian<Output = Self::Output>;
295
296 type MsbType: MaybePod + Endian<Output = Self::Output>;
301
302 fn new(value: Self::Output) -> Self;
304 fn get(&self) -> Self::Output;
306 fn set(&mut self, value: Self::Output);
308}
309
310#[cfg(all(test, feature = "std"))]
311mod tests {
312 #[test]
313 fn test_from_le_bytes() {
314 let value = u16::from_le_bytes([0x12, 0x34]);
315 assert_eq!(value, 0x3412);
316
317 let value = u32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
318 assert_eq!(value, 0x78563412);
319
320 let value = u64::from_le_bytes([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]);
321 assert_eq!(value, 0xf0debc9a78563412);
322 }
323
324 #[test]
325 fn test_from_be_bytes() {
326 let value = u16::from_be_bytes([0x12, 0x34]);
327 assert_eq!(value, 0x1234);
328
329 let value = u32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
330 assert_eq!(value, 0x12345678);
331
332 let value = u64::from_be_bytes([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]);
333 assert_eq!(value, 0x123456789abcdef0);
334 }
335}