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 {
48 #[cfg(target_endian = "little")]
49 {
50 matches!(self, Self::LittleEndian | Self::NativeEndian)
51 }
52 #[cfg(target_endian = "big")]
53 {
54 matches!(self, Self::LittleEndian)
55 }
56 }
57 pub fn read_u16(&self, bytes: [u8; 2]) -> u16 {
59 match self {
60 EndianType::NativeEndian => u16::from_ne_bytes(bytes),
61 EndianType::LittleEndian => u16::from_le_bytes(bytes),
62 EndianType::BigEndian => u16::from_be_bytes(bytes),
63 }
64 }
65
66 pub fn read_u32(&self, bytes: [u8; 4]) -> u32 {
68 match self {
69 EndianType::NativeEndian => u32::from_ne_bytes(bytes),
70 EndianType::LittleEndian => u32::from_le_bytes(bytes),
71 EndianType::BigEndian => u32::from_be_bytes(bytes),
72 }
73 }
74
75 pub fn read_u64(&self, bytes: [u8; 8]) -> u64 {
77 match self {
78 EndianType::NativeEndian => u64::from_ne_bytes(bytes),
79 EndianType::LittleEndian => u64::from_le_bytes(bytes),
80 EndianType::BigEndian => u64::from_be_bytes(bytes),
81 }
82 }
83
84 pub fn u16_bytes(&self, value: u16) -> [u8; 2] {
86 match self {
87 EndianType::NativeEndian => value.to_ne_bytes(),
88 EndianType::LittleEndian => value.to_le_bytes(),
89 EndianType::BigEndian => value.to_be_bytes(),
90 }
91 }
92
93 pub fn u32_bytes(&self, value: u32) -> [u8; 4] {
95 match self {
96 EndianType::NativeEndian => value.to_ne_bytes(),
97 EndianType::LittleEndian => value.to_le_bytes(),
98 EndianType::BigEndian => value.to_be_bytes(),
99 }
100 }
101
102 pub fn u64_bytes(&self, value: u64) -> [u8; 8] {
104 match self {
105 EndianType::NativeEndian => value.to_ne_bytes(),
106 EndianType::LittleEndian => value.to_le_bytes(),
107 EndianType::BigEndian => value.to_be_bytes(),
108 }
109 }
110}
111
112pub trait Endianness: Copy + Sized {
117 fn get() -> EndianType;
119
120 fn get_u16(bytes: [u8; 2]) -> u16;
122 fn set_u16(value: u16, bytes: &mut [u8; 2]);
124 fn get_u32(bytes: [u8; 4]) -> u32;
126 fn set_u32(value: u32, bytes: &mut [u8; 4]);
128 fn get_u64(bytes: [u8; 8]) -> u64;
130 fn set_u64(value: u64, bytes: &mut [u8; 8]);
132
133 fn get_u24(bytes: [u8; 3]) -> u32 {
135 let mut buf = [0u8; 4];
136 if Self::get().is_le() {
137 buf[..3].copy_from_slice(&bytes);
138 } else {
139 buf[1..].copy_from_slice(&bytes);
140 }
141 Self::get_u32(buf)
142 }
143
144 fn set_u24(value: u32, bytes: &mut [u8; 3]) {
146 let mut buf = [0u8; 4];
147 Self::set_u32(value, &mut buf);
148 if Self::get().is_le() {
149 bytes.copy_from_slice(&buf[..3]);
150 } else {
151 bytes.copy_from_slice(&buf[1..]);
152 }
153 }
154}
155
156#[repr(transparent)]
160#[derive(Debug, Copy, Clone)]
161#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
162pub struct NativeEndian;
163
164#[repr(transparent)]
168#[derive(Debug, Copy, Clone)]
169#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
170pub struct LittleEndian;
171
172#[repr(transparent)]
176#[derive(Debug, Copy, Clone)]
177#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
178pub struct BigEndian;
179
180impl Endianness for NativeEndian {
181 #[inline]
182 fn get() -> EndianType {
183 EndianType::NativeEndian
184 }
185
186 #[inline]
187 fn get_u16(bytes: [u8; 2]) -> u16 {
188 u16::from_ne_bytes(bytes)
189 }
190
191 #[inline]
192 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
193 bytes.copy_from_slice(&value.to_ne_bytes());
194 }
195
196 #[inline]
197 fn get_u32(bytes: [u8; 4]) -> u32 {
198 u32::from_ne_bytes(bytes)
199 }
200
201 #[inline]
202 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
203 bytes.copy_from_slice(&value.to_ne_bytes());
204 }
205
206 #[inline]
207 fn get_u64(bytes: [u8; 8]) -> u64 {
208 u64::from_ne_bytes(bytes)
209 }
210
211 #[inline]
212 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
213 bytes.copy_from_slice(&value.to_ne_bytes());
214 }
215}
216
217impl Endianness for LittleEndian {
218 #[inline]
219 fn get() -> EndianType {
220 EndianType::LittleEndian
221 }
222
223 #[inline]
224 fn get_u16(bytes: [u8; 2]) -> u16 {
225 u16::from_le_bytes(bytes)
226 }
227
228 #[inline]
229 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
230 bytes.copy_from_slice(&value.to_le_bytes());
231 }
232
233 #[inline]
234 fn get_u32(bytes: [u8; 4]) -> u32 {
235 u32::from_le_bytes(bytes)
236 }
237
238 #[inline]
239 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
240 bytes.copy_from_slice(&value.to_le_bytes());
241 }
242
243 #[inline]
244 fn get_u64(bytes: [u8; 8]) -> u64 {
245 u64::from_le_bytes(bytes)
246 }
247
248 #[inline]
249 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
250 bytes.copy_from_slice(&value.to_le_bytes());
251 }
252}
253impl Endianness for BigEndian {
254 #[inline]
255 fn get() -> EndianType {
256 EndianType::BigEndian
257 }
258
259 #[inline]
260 fn get_u16(bytes: [u8; 2]) -> u16 {
261 u16::from_be_bytes(bytes)
262 }
263
264 #[inline]
265 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
266 bytes.copy_from_slice(&value.to_be_bytes());
267 }
268
269 #[inline]
270 fn get_u32(bytes: [u8; 4]) -> u32 {
271 u32::from_be_bytes(bytes)
272 }
273
274 #[inline]
275 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
276 bytes.copy_from_slice(&value.to_be_bytes());
277 }
278
279 #[inline]
280 fn get_u64(bytes: [u8; 8]) -> u64 {
281 u64::from_be_bytes(bytes)
282 }
283
284 #[inline]
285 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
286 bytes.copy_from_slice(&value.to_be_bytes());
287 }
288}
289
290#[cfg(feature = "bytemuck")]
293pub trait MaybePod: bytemuck::Pod + bytemuck::Zeroable {}
294#[cfg(feature = "bytemuck")]
295impl<T: bytemuck::Pod + bytemuck::Zeroable> MaybePod for T {}
296#[cfg(not(feature = "bytemuck"))]
297pub trait MaybePod {}
298#[cfg(not(feature = "bytemuck"))]
299impl<T> MaybePod for T {}
300
301pub trait Endian {
314 type Output: MaybePod;
321
322 type LsbType: MaybePod + Endian<Output = Self::Output>;
327
328 type MsbType: MaybePod + Endian<Output = Self::Output>;
333
334 fn new(value: Self::Output) -> Self;
336 fn get(&self) -> Self::Output;
338 fn set(&mut self, value: Self::Output);
340}
341
342#[cfg(all(test, feature = "std"))]
343mod tests {
344 #[test]
345 fn test_from_le_bytes() {
346 let value = u16::from_le_bytes([0x12, 0x34]);
347 assert_eq!(value, 0x3412);
348
349 let value = u32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
350 assert_eq!(value, 0x78563412);
351
352 let value = u64::from_le_bytes([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]);
353 assert_eq!(value, 0xf0debc9a78563412);
354 }
355
356 #[test]
357 fn test_from_be_bytes() {
358 let value = u16::from_be_bytes([0x12, 0x34]);
359 assert_eq!(value, 0x1234);
360
361 let value = u32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
362 assert_eq!(value, 0x12345678);
363
364 let value = u64::from_be_bytes([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]);
365 assert_eq!(value, 0x123456789abcdef0);
366 }
367}