1#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
20pub enum EndianType {
21 #[default]
23 NativeEndian,
24 LittleEndian,
29 BigEndian,
34}
35
36impl core::fmt::Display for EndianType {
37 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38 match self {
39 Self::NativeEndian => write!(f, "native"),
40 Self::LittleEndian => write!(f, "little-endian"),
41 Self::BigEndian => write!(f, "big-endian"),
42 }
43 }
44}
45
46impl EndianType {
47 pub const fn is_le(&self) -> bool {
49 #[cfg(target_endian = "little")]
50 {
51 matches!(self, Self::LittleEndian | Self::NativeEndian)
52 }
53 #[cfg(target_endian = "big")]
54 {
55 matches!(self, Self::LittleEndian)
56 }
57 }
58 pub fn read_u16(&self, bytes: [u8; 2]) -> u16 {
60 match self {
61 EndianType::NativeEndian => u16::from_ne_bytes(bytes),
62 EndianType::LittleEndian => u16::from_le_bytes(bytes),
63 EndianType::BigEndian => u16::from_be_bytes(bytes),
64 }
65 }
66
67 pub fn read_u32(&self, bytes: [u8; 4]) -> u32 {
69 match self {
70 EndianType::NativeEndian => u32::from_ne_bytes(bytes),
71 EndianType::LittleEndian => u32::from_le_bytes(bytes),
72 EndianType::BigEndian => u32::from_be_bytes(bytes),
73 }
74 }
75
76 pub fn read_u64(&self, bytes: [u8; 8]) -> u64 {
78 match self {
79 EndianType::NativeEndian => u64::from_ne_bytes(bytes),
80 EndianType::LittleEndian => u64::from_le_bytes(bytes),
81 EndianType::BigEndian => u64::from_be_bytes(bytes),
82 }
83 }
84
85 pub fn u16_bytes(&self, value: u16) -> [u8; 2] {
87 match self {
88 EndianType::NativeEndian => value.to_ne_bytes(),
89 EndianType::LittleEndian => value.to_le_bytes(),
90 EndianType::BigEndian => value.to_be_bytes(),
91 }
92 }
93
94 pub fn u32_bytes(&self, value: u32) -> [u8; 4] {
96 match self {
97 EndianType::NativeEndian => value.to_ne_bytes(),
98 EndianType::LittleEndian => value.to_le_bytes(),
99 EndianType::BigEndian => value.to_be_bytes(),
100 }
101 }
102
103 pub fn u64_bytes(&self, value: u64) -> [u8; 8] {
105 match self {
106 EndianType::NativeEndian => value.to_ne_bytes(),
107 EndianType::LittleEndian => value.to_le_bytes(),
108 EndianType::BigEndian => value.to_be_bytes(),
109 }
110 }
111}
112
113pub trait Endianness: Copy + Sized {
118 fn get() -> EndianType;
120
121 fn get_u16(bytes: [u8; 2]) -> u16;
123 fn set_u16(value: u16, bytes: &mut [u8; 2]);
125 fn get_u32(bytes: [u8; 4]) -> u32;
127 fn set_u32(value: u32, bytes: &mut [u8; 4]);
129 fn get_u64(bytes: [u8; 8]) -> u64;
131 fn set_u64(value: u64, bytes: &mut [u8; 8]);
133
134 #[inline]
136 fn get_u24(bytes: [u8; 3]) -> u32 {
137 let mut buf = [0u8; 4];
138 if Self::get().is_le() {
139 buf[..3].copy_from_slice(&bytes);
140 } else {
141 buf[1..].copy_from_slice(&bytes);
142 }
143 Self::get_u32(buf)
144 }
145
146 #[inline]
148 fn set_u24(value: u32, bytes: &mut [u8; 3]) {
149 let mut buf = [0u8; 4];
150 Self::set_u32(value, &mut buf);
151 if Self::get().is_le() {
152 bytes.copy_from_slice(&buf[..3]);
153 } else {
154 bytes.copy_from_slice(&buf[1..]);
155 }
156 }
157}
158
159#[repr(transparent)]
163#[derive(Debug, Copy, Clone)]
164#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
165pub struct NativeEndian;
166
167#[repr(transparent)]
171#[derive(Debug, Copy, Clone)]
172#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
173pub struct LittleEndian;
174
175#[repr(transparent)]
179#[derive(Debug, Copy, Clone)]
180#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
181pub struct BigEndian;
182
183impl Endianness for NativeEndian {
184 #[inline]
185 fn get() -> EndianType {
186 EndianType::NativeEndian
187 }
188
189 #[inline]
190 fn get_u16(bytes: [u8; 2]) -> u16 {
191 u16::from_ne_bytes(bytes)
192 }
193
194 #[inline]
195 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
196 bytes.copy_from_slice(&value.to_ne_bytes());
197 }
198
199 #[inline]
200 fn get_u32(bytes: [u8; 4]) -> u32 {
201 u32::from_ne_bytes(bytes)
202 }
203
204 #[inline]
205 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
206 bytes.copy_from_slice(&value.to_ne_bytes());
207 }
208
209 #[inline]
210 fn get_u64(bytes: [u8; 8]) -> u64 {
211 u64::from_ne_bytes(bytes)
212 }
213
214 #[inline]
215 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
216 bytes.copy_from_slice(&value.to_ne_bytes());
217 }
218}
219
220impl Endianness for LittleEndian {
221 #[inline]
222 fn get() -> EndianType {
223 EndianType::LittleEndian
224 }
225
226 #[inline]
227 fn get_u16(bytes: [u8; 2]) -> u16 {
228 u16::from_le_bytes(bytes)
229 }
230
231 #[inline]
232 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
233 bytes.copy_from_slice(&value.to_le_bytes());
234 }
235
236 #[inline]
237 fn get_u32(bytes: [u8; 4]) -> u32 {
238 u32::from_le_bytes(bytes)
239 }
240
241 #[inline]
242 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
243 bytes.copy_from_slice(&value.to_le_bytes());
244 }
245
246 #[inline]
247 fn get_u64(bytes: [u8; 8]) -> u64 {
248 u64::from_le_bytes(bytes)
249 }
250
251 #[inline]
252 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
253 bytes.copy_from_slice(&value.to_le_bytes());
254 }
255}
256impl Endianness for BigEndian {
257 #[inline]
258 fn get() -> EndianType {
259 EndianType::BigEndian
260 }
261
262 #[inline]
263 fn get_u16(bytes: [u8; 2]) -> u16 {
264 u16::from_be_bytes(bytes)
265 }
266
267 #[inline]
268 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
269 bytes.copy_from_slice(&value.to_be_bytes());
270 }
271
272 #[inline]
273 fn get_u32(bytes: [u8; 4]) -> u32 {
274 u32::from_be_bytes(bytes)
275 }
276
277 #[inline]
278 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
279 bytes.copy_from_slice(&value.to_be_bytes());
280 }
281
282 #[inline]
283 fn get_u64(bytes: [u8; 8]) -> u64 {
284 u64::from_be_bytes(bytes)
285 }
286
287 #[inline]
288 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
289 bytes.copy_from_slice(&value.to_be_bytes());
290 }
291}
292
293#[cfg(feature = "bytemuck")]
296pub trait MaybePod: bytemuck::Pod + bytemuck::Zeroable {}
297#[cfg(feature = "bytemuck")]
298impl<T: bytemuck::Pod + bytemuck::Zeroable> MaybePod for T {}
299#[cfg(not(feature = "bytemuck"))]
301pub trait MaybePod {}
302#[cfg(not(feature = "bytemuck"))]
303impl<T> MaybePod for T {}
304
305pub trait Endian {
318 type Output: MaybePod;
325
326 type LsbType: MaybePod + Endian<Output = Self::Output>;
331
332 type MsbType: MaybePod + Endian<Output = Self::Output>;
337
338 fn new(value: Self::Output) -> Self;
340 fn get(&self) -> Self::Output;
342 fn set(&mut self, value: Self::Output);
344}
345
346#[cfg(all(test, feature = "std"))]
347mod tests {
348 #[test]
349 fn test_from_le_bytes() {
350 let value = u16::from_le_bytes([0x12, 0x34]);
351 assert_eq!(value, 0x3412);
352
353 let value = u32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
354 assert_eq!(value, 0x78563412);
355
356 let value = u64::from_le_bytes([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]);
357 assert_eq!(value, 0xf0debc9a78563412);
358 }
359
360 #[test]
361 fn test_from_be_bytes() {
362 let value = u16::from_be_bytes([0x12, 0x34]);
363 assert_eq!(value, 0x1234);
364
365 let value = u32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
366 assert_eq!(value, 0x12345678);
367
368 let value = u64::from_be_bytes([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]);
369 assert_eq!(value, 0x123456789abcdef0);
370 }
371}