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 fn get_u24(bytes: [u8; 3]) -> u32 {
136 let mut buf = [0u8; 4];
137 if Self::get().is_le() {
138 buf[..3].copy_from_slice(&bytes);
139 } else {
140 buf[1..].copy_from_slice(&bytes);
141 }
142 Self::get_u32(buf)
143 }
144
145 fn set_u24(value: u32, bytes: &mut [u8; 3]) {
147 let mut buf = [0u8; 4];
148 Self::set_u32(value, &mut buf);
149 if Self::get().is_le() {
150 bytes.copy_from_slice(&buf[..3]);
151 } else {
152 bytes.copy_from_slice(&buf[1..]);
153 }
154 }
155}
156
157#[repr(transparent)]
161#[derive(Debug, Copy, Clone)]
162#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
163pub struct NativeEndian;
164
165#[repr(transparent)]
169#[derive(Debug, Copy, Clone)]
170#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
171pub struct LittleEndian;
172
173#[repr(transparent)]
177#[derive(Debug, Copy, Clone)]
178#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
179pub struct BigEndian;
180
181impl Endianness for NativeEndian {
182 #[inline]
183 fn get() -> EndianType {
184 EndianType::NativeEndian
185 }
186
187 #[inline]
188 fn get_u16(bytes: [u8; 2]) -> u16 {
189 u16::from_ne_bytes(bytes)
190 }
191
192 #[inline]
193 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
194 bytes.copy_from_slice(&value.to_ne_bytes());
195 }
196
197 #[inline]
198 fn get_u32(bytes: [u8; 4]) -> u32 {
199 u32::from_ne_bytes(bytes)
200 }
201
202 #[inline]
203 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
204 bytes.copy_from_slice(&value.to_ne_bytes());
205 }
206
207 #[inline]
208 fn get_u64(bytes: [u8; 8]) -> u64 {
209 u64::from_ne_bytes(bytes)
210 }
211
212 #[inline]
213 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
214 bytes.copy_from_slice(&value.to_ne_bytes());
215 }
216}
217
218impl Endianness for LittleEndian {
219 #[inline]
220 fn get() -> EndianType {
221 EndianType::LittleEndian
222 }
223
224 #[inline]
225 fn get_u16(bytes: [u8; 2]) -> u16 {
226 u16::from_le_bytes(bytes)
227 }
228
229 #[inline]
230 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
231 bytes.copy_from_slice(&value.to_le_bytes());
232 }
233
234 #[inline]
235 fn get_u32(bytes: [u8; 4]) -> u32 {
236 u32::from_le_bytes(bytes)
237 }
238
239 #[inline]
240 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
241 bytes.copy_from_slice(&value.to_le_bytes());
242 }
243
244 #[inline]
245 fn get_u64(bytes: [u8; 8]) -> u64 {
246 u64::from_le_bytes(bytes)
247 }
248
249 #[inline]
250 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
251 bytes.copy_from_slice(&value.to_le_bytes());
252 }
253}
254impl Endianness for BigEndian {
255 #[inline]
256 fn get() -> EndianType {
257 EndianType::BigEndian
258 }
259
260 #[inline]
261 fn get_u16(bytes: [u8; 2]) -> u16 {
262 u16::from_be_bytes(bytes)
263 }
264
265 #[inline]
266 fn set_u16(value: u16, bytes: &mut [u8; 2]) {
267 bytes.copy_from_slice(&value.to_be_bytes());
268 }
269
270 #[inline]
271 fn get_u32(bytes: [u8; 4]) -> u32 {
272 u32::from_be_bytes(bytes)
273 }
274
275 #[inline]
276 fn set_u32(value: u32, bytes: &mut [u8; 4]) {
277 bytes.copy_from_slice(&value.to_be_bytes());
278 }
279
280 #[inline]
281 fn get_u64(bytes: [u8; 8]) -> u64 {
282 u64::from_be_bytes(bytes)
283 }
284
285 #[inline]
286 fn set_u64(value: u64, bytes: &mut [u8; 8]) {
287 bytes.copy_from_slice(&value.to_be_bytes());
288 }
289}
290
291#[cfg(feature = "bytemuck")]
294pub trait MaybePod: bytemuck::Pod + bytemuck::Zeroable {}
295#[cfg(feature = "bytemuck")]
296impl<T: bytemuck::Pod + bytemuck::Zeroable> MaybePod for T {}
297#[cfg(not(feature = "bytemuck"))]
299pub trait MaybePod {}
300#[cfg(not(feature = "bytemuck"))]
301impl<T> MaybePod for T {}
302
303pub trait Endian {
316 type Output: MaybePod;
323
324 type LsbType: MaybePod + Endian<Output = Self::Output>;
329
330 type MsbType: MaybePod + Endian<Output = Self::Output>;
335
336 fn new(value: Self::Output) -> Self;
338 fn get(&self) -> Self::Output;
340 fn set(&mut self, value: Self::Output);
342}
343
344#[cfg(all(test, feature = "std"))]
345mod tests {
346 #[test]
347 fn test_from_le_bytes() {
348 let value = u16::from_le_bytes([0x12, 0x34]);
349 assert_eq!(value, 0x3412);
350
351 let value = u32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
352 assert_eq!(value, 0x78563412);
353
354 let value = u64::from_le_bytes([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]);
355 assert_eq!(value, 0xf0debc9a78563412);
356 }
357
358 #[test]
359 fn test_from_be_bytes() {
360 let value = u16::from_be_bytes([0x12, 0x34]);
361 assert_eq!(value, 0x1234);
362
363 let value = u32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
364 assert_eq!(value, 0x12345678);
365
366 let value = u64::from_be_bytes([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]);
367 assert_eq!(value, 0x123456789abcdef0);
368 }
369}