1use crate::pod::Pod;
4use core::fmt::{self, Debug};
5use core::marker::PhantomData;
6
7pub trait Endian: Debug + Default + Clone + Copy + PartialEq + Eq + 'static {
14 fn from_big_endian(big_endian: bool) -> Option<Self>;
18
19 fn from_little_endian(little_endian: bool) -> Option<Self> {
23 Self::from_big_endian(!little_endian)
24 }
25
26 fn is_big_endian(self) -> bool;
28
29 #[inline]
31 fn is_little_endian(self) -> bool {
32 !self.is_big_endian()
33 }
34
35 #[inline]
37 fn read_u16(self, n: [u8; 2]) -> u16 {
38 if self.is_big_endian() {
39 u16::from_be_bytes(n)
40 } else {
41 u16::from_le_bytes(n)
42 }
43 }
44
45 #[inline]
47 fn read_u32(self, n: [u8; 4]) -> u32 {
48 if self.is_big_endian() {
49 u32::from_be_bytes(n)
50 } else {
51 u32::from_le_bytes(n)
52 }
53 }
54
55 #[inline]
57 fn read_u64(self, n: [u8; 8]) -> u64 {
58 if self.is_big_endian() {
59 u64::from_be_bytes(n)
60 } else {
61 u64::from_le_bytes(n)
62 }
63 }
64
65 #[inline]
67 fn read_i16(self, n: [u8; 2]) -> i16 {
68 if self.is_big_endian() {
69 i16::from_be_bytes(n)
70 } else {
71 i16::from_le_bytes(n)
72 }
73 }
74
75 #[inline]
77 fn read_i32(self, n: [u8; 4]) -> i32 {
78 if self.is_big_endian() {
79 i32::from_be_bytes(n)
80 } else {
81 i32::from_le_bytes(n)
82 }
83 }
84
85 #[inline]
87 fn read_i64(self, n: [u8; 8]) -> i64 {
88 if self.is_big_endian() {
89 i64::from_be_bytes(n)
90 } else {
91 i64::from_le_bytes(n)
92 }
93 }
94
95 #[inline]
97 fn write_u16(self, n: u16) -> [u8; 2] {
98 if self.is_big_endian() {
99 u16::to_be_bytes(n)
100 } else {
101 u16::to_le_bytes(n)
102 }
103 }
104
105 #[inline]
107 fn write_u32(self, n: u32) -> [u8; 4] {
108 if self.is_big_endian() {
109 u32::to_be_bytes(n)
110 } else {
111 u32::to_le_bytes(n)
112 }
113 }
114
115 #[inline]
117 fn write_u64(self, n: u64) -> [u8; 8] {
118 if self.is_big_endian() {
119 u64::to_be_bytes(n)
120 } else {
121 u64::to_le_bytes(n)
122 }
123 }
124
125 #[inline]
127 fn write_i16(self, n: i16) -> [u8; 2] {
128 if self.is_big_endian() {
129 i16::to_be_bytes(n)
130 } else {
131 i16::to_le_bytes(n)
132 }
133 }
134
135 #[inline]
137 fn write_i32(self, n: i32) -> [u8; 4] {
138 if self.is_big_endian() {
139 i32::to_be_bytes(n)
140 } else {
141 i32::to_le_bytes(n)
142 }
143 }
144
145 #[inline]
147 fn write_i64(self, n: i64) -> [u8; 8] {
148 if self.is_big_endian() {
149 i64::to_be_bytes(n)
150 } else {
151 i64::to_le_bytes(n)
152 }
153 }
154}
155
156pub trait FixedEndian: Endian {
158 const FIXED: Self;
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
164pub enum Endianness {
165 Little,
167 Big,
169}
170
171impl Default for Endianness {
172 #[cfg(target_endian = "little")]
173 #[inline]
174 fn default() -> Endianness {
175 Endianness::Little
176 }
177
178 #[cfg(target_endian = "big")]
179 #[inline]
180 fn default() -> Endianness {
181 Endianness::Big
182 }
183}
184
185impl Endian for Endianness {
186 #[inline]
187 fn from_big_endian(big_endian: bool) -> Option<Self> {
188 Some(if big_endian {
189 Endianness::Big
190 } else {
191 Endianness::Little
192 })
193 }
194
195 #[inline]
196 fn is_big_endian(self) -> bool {
197 self != Endianness::Little
198 }
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
203pub struct LittleEndian;
204
205impl Default for LittleEndian {
206 #[inline]
207 fn default() -> LittleEndian {
208 LittleEndian
209 }
210}
211
212impl Endian for LittleEndian {
213 #[inline]
214 fn from_big_endian(big_endian: bool) -> Option<Self> {
215 if big_endian {
216 None
217 } else {
218 Some(LittleEndian)
219 }
220 }
221
222 #[inline]
223 fn is_big_endian(self) -> bool {
224 false
225 }
226}
227
228impl FixedEndian for LittleEndian {
229 const FIXED: Self = LittleEndian;
230}
231
232#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
234pub struct BigEndian;
235
236impl Default for BigEndian {
237 #[inline]
238 fn default() -> BigEndian {
239 BigEndian
240 }
241}
242
243impl Endian for BigEndian {
244 #[inline]
245 fn from_big_endian(big_endian: bool) -> Option<Self> {
246 if big_endian {
247 Some(BigEndian)
248 } else {
249 None
250 }
251 }
252
253 #[inline]
254 fn is_big_endian(self) -> bool {
255 true
256 }
257}
258
259impl FixedEndian for BigEndian {
260 const FIXED: Self = BigEndian;
261}
262
263#[cfg(target_endian = "little")]
265pub type NativeEndian = LittleEndian;
266
267#[cfg(target_endian = "little")]
268#[allow(non_upper_case_globals)]
269#[doc(hidden)]
270pub const NativeEndian: LittleEndian = LittleEndian;
271
272#[cfg(target_endian = "big")]
274pub type NativeEndian = BigEndian;
275
276#[cfg(target_endian = "big")]
277#[allow(non_upper_case_globals)]
278#[doc(hidden)]
279pub const NativeEndian: BigEndian = BigEndian;
280
281macro_rules! unsafe_impl_endian_pod {
282 ($($struct_name:ident),+ $(,)?) => {
283 $(
284 unsafe impl<E: Endian> Pod for $struct_name<E> { }
285 )+
286 }
287}
288
289#[deprecated]
291pub type U16Bytes<E> = U16<E>;
292
293#[deprecated]
295pub type U32Bytes<E> = U32<E>;
296
297#[deprecated]
299pub type U64Bytes<E> = U64<E>;
300
301#[deprecated]
303pub type I16Bytes<E> = I16<E>;
304
305#[deprecated]
307pub type I32Bytes<E> = I32<E>;
308
309#[deprecated]
311pub type I64Bytes<E> = I64<E>;
312
313#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
315#[repr(transparent)]
316pub struct U16<E: Endian>([u8; 2], PhantomData<E>);
317
318impl<E: Endian> U16<E> {
319 pub const fn from_bytes(n: [u8; 2]) -> Self {
321 Self(n, PhantomData)
322 }
323
324 pub fn new(e: E, n: u16) -> Self {
326 Self(e.write_u16(n), PhantomData)
327 }
328
329 pub fn get(self, e: E) -> u16 {
331 e.read_u16(self.0)
332 }
333
334 pub fn set(&mut self, e: E, n: u16) {
336 self.0 = e.write_u16(n);
337 }
338}
339
340#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
342#[repr(transparent)]
343pub struct U32<E: Endian>([u8; 4], PhantomData<E>);
344
345impl<E: Endian> U32<E> {
346 pub const fn from_bytes(n: [u8; 4]) -> Self {
348 Self(n, PhantomData)
349 }
350
351 pub fn new(e: E, n: u32) -> Self {
353 Self(e.write_u32(n), PhantomData)
354 }
355
356 pub fn get(self, e: E) -> u32 {
358 e.read_u32(self.0)
359 }
360
361 pub fn set(&mut self, e: E, n: u32) {
363 self.0 = e.write_u32(n);
364 }
365}
366
367#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
369#[repr(transparent)]
370pub struct U64<E: Endian>([u8; 8], PhantomData<E>);
371
372impl<E: Endian> U64<E> {
373 pub const fn from_bytes(n: [u8; 8]) -> Self {
375 Self(n, PhantomData)
376 }
377
378 pub fn new(e: E, n: u64) -> Self {
380 Self(e.write_u64(n), PhantomData)
381 }
382
383 pub fn get(self, e: E) -> u64 {
385 e.read_u64(self.0)
386 }
387
388 pub fn set(&mut self, e: E, n: u64) {
390 self.0 = e.write_u64(n);
391 }
392}
393
394#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
396#[repr(transparent)]
397pub struct I16<E: Endian>([u8; 2], PhantomData<E>);
398
399impl<E: Endian> I16<E> {
400 pub const fn from_bytes(n: [u8; 2]) -> Self {
402 Self(n, PhantomData)
403 }
404
405 pub fn new(e: E, n: i16) -> Self {
407 Self(e.write_i16(n), PhantomData)
408 }
409
410 pub fn get(self, e: E) -> i16 {
412 e.read_i16(self.0)
413 }
414
415 pub fn set(&mut self, e: E, n: i16) {
417 self.0 = e.write_i16(n);
418 }
419}
420
421#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
423#[repr(transparent)]
424pub struct I32<E: Endian>([u8; 4], PhantomData<E>);
425
426impl<E: Endian> I32<E> {
427 pub const fn from_bytes(n: [u8; 4]) -> Self {
429 Self(n, PhantomData)
430 }
431
432 pub fn new(e: E, n: i32) -> Self {
434 Self(e.write_i32(n), PhantomData)
435 }
436
437 pub fn get(self, e: E) -> i32 {
439 e.read_i32(self.0)
440 }
441
442 pub fn set(&mut self, e: E, n: i32) {
444 self.0 = e.write_i32(n);
445 }
446}
447
448#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
450#[repr(transparent)]
451pub struct I64<E: Endian>([u8; 8], PhantomData<E>);
452
453impl<E: Endian> I64<E> {
454 pub const fn from_bytes(n: [u8; 8]) -> Self {
456 Self(n, PhantomData)
457 }
458
459 pub fn new(e: E, n: i64) -> Self {
461 Self(e.write_i64(n), PhantomData)
462 }
463
464 pub fn get(self, e: E) -> i64 {
466 e.read_i64(self.0)
467 }
468
469 pub fn set(&mut self, e: E, n: i64) {
471 self.0 = e.write_i64(n);
472 }
473}
474
475impl<E: Endian> fmt::Debug for U16<E> {
476 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
477 write!(f, "U16({:02x}{:02x})", self.0[0], self.0[1],)
478 }
479}
480
481impl<E: Endian> fmt::Debug for U32<E> {
482 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
483 write!(
484 f,
485 "U32({:02x}{:02x}{:02x}{:02x})",
486 self.0[0], self.0[1], self.0[2], self.0[3],
487 )
488 }
489}
490
491impl<E: Endian> fmt::Debug for U64<E> {
492 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493 write!(
494 f,
495 "U64({:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x})",
496 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7],
497 )
498 }
499}
500
501impl<E: Endian> fmt::Debug for I16<E> {
502 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503 write!(f, "I16({:02x}{:02x})", self.0[0], self.0[1],)
504 }
505}
506
507impl<E: Endian> fmt::Debug for I32<E> {
508 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509 write!(
510 f,
511 "I32({:02x}{:02x}{:02x}{:02x})",
512 self.0[0], self.0[1], self.0[2], self.0[3],
513 )
514 }
515}
516
517impl<E: Endian> fmt::Debug for I64<E> {
518 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519 write!(
520 f,
521 "I64({:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x})",
522 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7],
523 )
524 }
525}
526
527impl<E: FixedEndian> From<u16> for U16<E> {
528 fn from(val: u16) -> Self {
529 Self::new(E::FIXED, val)
530 }
531}
532
533impl<E: FixedEndian> From<U16<E>> for u16 {
534 fn from(val: U16<E>) -> Self {
535 val.get(E::FIXED)
536 }
537}
538
539impl<E: FixedEndian> From<u32> for U32<E> {
540 fn from(val: u32) -> Self {
541 Self::new(E::FIXED, val)
542 }
543}
544
545impl<E: FixedEndian> From<U32<E>> for u32 {
546 fn from(val: U32<E>) -> Self {
547 val.get(E::FIXED)
548 }
549}
550
551impl<E: FixedEndian> From<u64> for U64<E> {
552 fn from(val: u64) -> Self {
553 Self::new(E::FIXED, val)
554 }
555}
556
557impl<E: FixedEndian> From<U64<E>> for u64 {
558 fn from(val: U64<E>) -> Self {
559 val.get(E::FIXED)
560 }
561}
562
563impl<E: FixedEndian> From<i16> for I16<E> {
564 fn from(val: i16) -> Self {
565 Self::new(E::FIXED, val)
566 }
567}
568
569impl<E: FixedEndian> From<I16<E>> for i16 {
570 fn from(val: I16<E>) -> Self {
571 val.get(E::FIXED)
572 }
573}
574
575impl<E: FixedEndian> From<i32> for I32<E> {
576 fn from(val: i32) -> Self {
577 Self::new(E::FIXED, val)
578 }
579}
580
581impl<E: FixedEndian> From<I32<E>> for i32 {
582 fn from(val: I32<E>) -> Self {
583 val.get(E::FIXED)
584 }
585}
586
587impl<E: FixedEndian> From<i64> for I64<E> {
588 fn from(val: i64) -> Self {
589 Self::new(E::FIXED, val)
590 }
591}
592
593impl<E: FixedEndian> From<I64<E>> for i64 {
594 fn from(val: I64<E>) -> Self {
595 val.get(E::FIXED)
596 }
597}
598
599unsafe_impl_endian_pod!(U16, U32, U64, I16, I32, I64);