1//! Types for compile-time and run-time endianness.
2
3use crate::pod::Pod;
4use core::fmt::{self, Debug};
5use core::marker::PhantomData;
6
7/// A trait for using an endianness specification.
8///
9/// Provides methods for converting between the specified endianness and
10/// the native endianness of the target machine.
11///
12/// This trait does not require that the endianness is known at compile time.
13pub trait Endian: Debug + Default + Clone + Copy + PartialEq + Eq + 'static {
14 /// Construct a specification for the endianness of some values.
15 ///
16 /// Returns `None` if the type does not support specifying the given endianness.
17 fn from_big_endian(big_endian: bool) -> Option<Self>;
18
19 /// Construct a specification for the endianness of some values.
20 ///
21 /// Returns `None` if the type does not support specifying the given endianness.
22 fn from_little_endian(little_endian: bool) -> Option<Self> {
23 Self::from_big_endian(!little_endian)
24 }
25
26 /// Return true for big endian byte order.
27 fn is_big_endian(self) -> bool;
28
29 /// Return true for little endian byte order.
30 #[inline]
31 fn is_little_endian(self) -> bool {
32 !self.is_big_endian()
33 }
34
35 /// Converts an unsigned 16 bit integer to native endian.
36 #[inline]
37 fn read_u16(self, n: u16) -> u16 {
38 if self.is_big_endian() {
39 u16::from_be(n)
40 } else {
41 u16::from_le(n)
42 }
43 }
44
45 /// Converts an unsigned 32 bit integer to native endian.
46 #[inline]
47 fn read_u32(self, n: u32) -> u32 {
48 if self.is_big_endian() {
49 u32::from_be(n)
50 } else {
51 u32::from_le(n)
52 }
53 }
54
55 /// Converts an unsigned 64 bit integer to native endian.
56 #[inline]
57 fn read_u64(self, n: u64) -> u64 {
58 if self.is_big_endian() {
59 u64::from_be(n)
60 } else {
61 u64::from_le(n)
62 }
63 }
64
65 /// Converts a signed 16 bit integer to native endian.
66 #[inline]
67 fn read_i16(self, n: i16) -> i16 {
68 if self.is_big_endian() {
69 i16::from_be(n)
70 } else {
71 i16::from_le(n)
72 }
73 }
74
75 /// Converts a signed 32 bit integer to native endian.
76 #[inline]
77 fn read_i32(self, n: i32) -> i32 {
78 if self.is_big_endian() {
79 i32::from_be(n)
80 } else {
81 i32::from_le(n)
82 }
83 }
84
85 /// Converts a signed 64 bit integer to native endian.
86 #[inline]
87 fn read_i64(self, n: i64) -> i64 {
88 if self.is_big_endian() {
89 i64::from_be(n)
90 } else {
91 i64::from_le(n)
92 }
93 }
94
95 /// Converts an unaligned unsigned 16 bit integer to native endian.
96 #[inline]
97 fn read_u16_bytes(self, n: [u8; 2]) -> u16 {
98 if self.is_big_endian() {
99 u16::from_be_bytes(n)
100 } else {
101 u16::from_le_bytes(n)
102 }
103 }
104
105 /// Converts an unaligned unsigned 32 bit integer to native endian.
106 #[inline]
107 fn read_u32_bytes(self, n: [u8; 4]) -> u32 {
108 if self.is_big_endian() {
109 u32::from_be_bytes(n)
110 } else {
111 u32::from_le_bytes(n)
112 }
113 }
114
115 /// Converts an unaligned unsigned 64 bit integer to native endian.
116 #[inline]
117 fn read_u64_bytes(self, n: [u8; 8]) -> u64 {
118 if self.is_big_endian() {
119 u64::from_be_bytes(n)
120 } else {
121 u64::from_le_bytes(n)
122 }
123 }
124
125 /// Converts an unaligned signed 16 bit integer to native endian.
126 #[inline]
127 fn read_i16_bytes(self, n: [u8; 2]) -> i16 {
128 if self.is_big_endian() {
129 i16::from_be_bytes(n)
130 } else {
131 i16::from_le_bytes(n)
132 }
133 }
134
135 /// Converts an unaligned signed 32 bit integer to native endian.
136 #[inline]
137 fn read_i32_bytes(self, n: [u8; 4]) -> i32 {
138 if self.is_big_endian() {
139 i32::from_be_bytes(n)
140 } else {
141 i32::from_le_bytes(n)
142 }
143 }
144
145 /// Converts an unaligned signed 64 bit integer to native endian.
146 #[inline]
147 fn read_i64_bytes(self, n: [u8; 8]) -> i64 {
148 if self.is_big_endian() {
149 i64::from_be_bytes(n)
150 } else {
151 i64::from_le_bytes(n)
152 }
153 }
154
155 /// Converts an unsigned 16 bit integer from native endian.
156 #[inline]
157 fn write_u16(self, n: u16) -> u16 {
158 if self.is_big_endian() {
159 u16::to_be(n)
160 } else {
161 u16::to_le(n)
162 }
163 }
164
165 /// Converts an unsigned 32 bit integer from native endian.
166 #[inline]
167 fn write_u32(self, n: u32) -> u32 {
168 if self.is_big_endian() {
169 u32::to_be(n)
170 } else {
171 u32::to_le(n)
172 }
173 }
174
175 /// Converts an unsigned 64 bit integer from native endian.
176 #[inline]
177 fn write_u64(self, n: u64) -> u64 {
178 if self.is_big_endian() {
179 u64::to_be(n)
180 } else {
181 u64::to_le(n)
182 }
183 }
184
185 /// Converts a signed 16 bit integer from native endian.
186 #[inline]
187 fn write_i16(self, n: i16) -> i16 {
188 if self.is_big_endian() {
189 i16::to_be(n)
190 } else {
191 i16::to_le(n)
192 }
193 }
194
195 /// Converts a signed 32 bit integer from native endian.
196 #[inline]
197 fn write_i32(self, n: i32) -> i32 {
198 if self.is_big_endian() {
199 i32::to_be(n)
200 } else {
201 i32::to_le(n)
202 }
203 }
204
205 /// Converts a signed 64 bit integer from native endian.
206 #[inline]
207 fn write_i64(self, n: i64) -> i64 {
208 if self.is_big_endian() {
209 i64::to_be(n)
210 } else {
211 i64::to_le(n)
212 }
213 }
214
215 /// Converts an unaligned unsigned 16 bit integer from native endian.
216 #[inline]
217 fn write_u16_bytes(self, n: u16) -> [u8; 2] {
218 if self.is_big_endian() {
219 u16::to_be_bytes(n)
220 } else {
221 u16::to_le_bytes(n)
222 }
223 }
224
225 /// Converts an unaligned unsigned 32 bit integer from native endian.
226 #[inline]
227 fn write_u32_bytes(self, n: u32) -> [u8; 4] {
228 if self.is_big_endian() {
229 u32::to_be_bytes(n)
230 } else {
231 u32::to_le_bytes(n)
232 }
233 }
234
235 /// Converts an unaligned unsigned 64 bit integer from native endian.
236 #[inline]
237 fn write_u64_bytes(self, n: u64) -> [u8; 8] {
238 if self.is_big_endian() {
239 u64::to_be_bytes(n)
240 } else {
241 u64::to_le_bytes(n)
242 }
243 }
244
245 /// Converts an unaligned signed 16 bit integer from native endian.
246 #[inline]
247 fn write_i16_bytes(self, n: i16) -> [u8; 2] {
248 if self.is_big_endian() {
249 i16::to_be_bytes(n)
250 } else {
251 i16::to_le_bytes(n)
252 }
253 }
254
255 /// Converts an unaligned signed 32 bit integer from native endian.
256 #[inline]
257 fn write_i32_bytes(self, n: i32) -> [u8; 4] {
258 if self.is_big_endian() {
259 i32::to_be_bytes(n)
260 } else {
261 i32::to_le_bytes(n)
262 }
263 }
264
265 /// Converts an unaligned signed 64 bit integer from native endian.
266 #[inline]
267 fn write_i64_bytes(self, n: i64) -> [u8; 8] {
268 if self.is_big_endian() {
269 i64::to_be_bytes(n)
270 } else {
271 i64::to_le_bytes(n)
272 }
273 }
274}
275
276/// An endianness that is selectable at run-time.
277#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
278pub enum Endianness {
279 /// Little endian byte order.
280 Little,
281 /// Big endian byte order.
282 Big,
283}
284
285impl Default for Endianness {
286 #[cfg(target_endian = "little")]
287 #[inline]
288 fn default() -> Endianness {
289 Endianness::Little
290 }
291
292 #[cfg(target_endian = "big")]
293 #[inline]
294 fn default() -> Endianness {
295 Endianness::Big
296 }
297}
298
299impl Endian for Endianness {
300 #[inline]
301 fn from_big_endian(big_endian: bool) -> Option<Self> {
302 Some(if big_endian {
303 Endianness::Big
304 } else {
305 Endianness::Little
306 })
307 }
308
309 #[inline]
310 fn is_big_endian(self) -> bool {
311 self != Endianness::Little
312 }
313}
314
315/// Compile-time little endian byte order.
316#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
317pub struct LittleEndian;
318
319impl Default for LittleEndian {
320 #[inline]
321 fn default() -> LittleEndian {
322 LittleEndian
323 }
324}
325
326impl Endian for LittleEndian {
327 #[inline]
328 fn from_big_endian(big_endian: bool) -> Option<Self> {
329 if big_endian {
330 None
331 } else {
332 Some(LittleEndian)
333 }
334 }
335
336 #[inline]
337 fn is_big_endian(self) -> bool {
338 false
339 }
340}
341
342/// Compile-time big endian byte order.
343#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
344pub struct BigEndian;
345
346impl Default for BigEndian {
347 #[inline]
348 fn default() -> BigEndian {
349 BigEndian
350 }
351}
352
353impl Endian for BigEndian {
354 #[inline]
355 fn from_big_endian(big_endian: bool) -> Option<Self> {
356 if big_endian {
357 Some(BigEndian)
358 } else {
359 None
360 }
361 }
362
363 #[inline]
364 fn is_big_endian(self) -> bool {
365 true
366 }
367}
368
369/// The native endianness for the target platform.
370#[cfg(target_endian = "little")]
371pub type NativeEndian = LittleEndian;
372
373#[cfg(target_endian = "little")]
374#[allow(non_upper_case_globals)]
375#[doc(hidden)]
376pub const NativeEndian: LittleEndian = LittleEndian;
377
378/// The native endianness for the target platform.
379#[cfg(target_endian = "big")]
380pub type NativeEndian = BigEndian;
381
382#[cfg(target_endian = "big")]
383#[allow(non_upper_case_globals)]
384#[doc(hidden)]
385pub const NativeEndian: BigEndian = BigEndian;
386
387macro_rules! unsafe_impl_endian_pod {
388 ($($struct_name:ident),+ $(,)?) => {
389 $(
390 unsafe impl<E: Endian> Pod for $struct_name<E> { }
391 )+
392 }
393}
394
395#[cfg(not(feature = "unaligned"))]
396mod aligned {
397 use super::{fmt, Endian, PhantomData, Pod};
398
399 /// A `u16` value with an externally specified endianness of type `E`.
400 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
401 #[repr(transparent)]
402 pub struct U16<E: Endian>(u16, PhantomData<E>);
403
404 impl<E: Endian> U16<E> {
405 /// Construct a new value given bytes that already have the required endianness.
406 pub fn from_bytes(n: [u8; 2]) -> Self {
407 Self(u16::from_ne_bytes(n), PhantomData)
408 }
409
410 /// Construct a new value given a native endian value.
411 pub fn new(e: E, n: u16) -> Self {
412 Self(e.write_u16(n), PhantomData)
413 }
414
415 /// Return the value as a native endian value.
416 pub fn get(self, e: E) -> u16 {
417 e.read_u16(self.0)
418 }
419
420 /// Set the value given a native endian value.
421 pub fn set(&mut self, e: E, n: u16) {
422 self.0 = e.write_u16(n);
423 }
424 }
425
426 /// A `u32` value with an externally specified endianness of type `E`.
427 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
428 #[repr(transparent)]
429 pub struct U32<E: Endian>(u32, PhantomData<E>);
430
431 impl<E: Endian> U32<E> {
432 /// Construct a new value given bytes that already have the required endianness.
433 pub fn from_bytes(n: [u8; 4]) -> Self {
434 Self(u32::from_ne_bytes(n), PhantomData)
435 }
436
437 /// Construct a new value given a native endian value.
438 pub fn new(e: E, n: u32) -> Self {
439 Self(e.write_u32(n), PhantomData)
440 }
441 /// Return the value as a native endian value.
442 pub fn get(self, e: E) -> u32 {
443 e.read_u32(self.0)
444 }
445 /// Set the value given a native endian value.
446 pub fn set(&mut self, e: E, n: u32) {
447 self.0 = e.write_u32(n);
448 }
449 }
450
451 /// A `u64` value with an externally specified endianness of type `E`.
452 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
453 #[repr(transparent)]
454 pub struct U64<E: Endian>(u64, PhantomData<E>);
455
456 impl<E: Endian> U64<E> {
457 /// Construct a new value given bytes that already have the required endianness.
458 pub fn from_bytes(n: [u8; 8]) -> Self {
459 Self(u64::from_ne_bytes(n), PhantomData)
460 }
461
462 /// Construct a new value given a native endian value.
463 pub fn new(e: E, n: u64) -> Self {
464 Self(e.write_u64(n), PhantomData)
465 }
466 /// Return the value as a native endian value.
467 pub fn get(self, e: E) -> u64 {
468 e.read_u64(self.0)
469 }
470 /// Set the value given a native endian value.
471 pub fn set(&mut self, e: E, n: u64) {
472 self.0 = e.write_u64(n);
473 }
474 }
475
476 /// An `i16` value with an externally specified endianness of type `E`.
477 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
478 #[repr(transparent)]
479 pub struct I16<E: Endian>(i16, PhantomData<E>);
480
481 impl<E: Endian> I16<E> {
482 /// Construct a new value given bytes that already have the required endianness.
483 pub fn from_bytes(n: [u8; 2]) -> Self {
484 Self(i16::from_ne_bytes(n), PhantomData)
485 }
486
487 /// Construct a new value given a native endian value.
488 pub fn new(e: E, n: i16) -> Self {
489 Self(e.write_i16(n), PhantomData)
490 }
491 /// Return the value as a native endian value.
492 pub fn get(self, e: E) -> i16 {
493 e.read_i16(self.0)
494 }
495 /// Set the value given a native endian value.
496 pub fn set(&mut self, e: E, n: i16) {
497 self.0 = e.write_i16(n);
498 }
499 }
500
501 /// An `i32` value with an externally specified endianness of type `E`.
502 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
503 #[repr(transparent)]
504 pub struct I32<E: Endian>(i32, PhantomData<E>);
505
506 impl<E: Endian> I32<E> {
507 /// Construct a new value given bytes that already have the required endianness.
508 pub fn from_bytes(n: [u8; 4]) -> Self {
509 Self(i32::from_ne_bytes(n), PhantomData)
510 }
511
512 /// Construct a new value given a native endian value.
513 pub fn new(e: E, n: i32) -> Self {
514 Self(e.write_i32(n), PhantomData)
515 }
516 /// Return the value as a native endian value.
517 pub fn get(self, e: E) -> i32 {
518 e.read_i32(self.0)
519 }
520 /// Set the value given a native endian value.
521 pub fn set(&mut self, e: E, n: i32) {
522 self.0 = e.write_i32(n);
523 }
524 }
525
526 /// An `i64` value with an externally specified endianness of type `E`.
527 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
528 #[repr(transparent)]
529 pub struct I64<E: Endian>(i64, PhantomData<E>);
530
531 impl<E: Endian> I64<E> {
532 /// Construct a new value given bytes that already have the required endianness.
533 pub fn from_bytes(n: [u8; 8]) -> Self {
534 Self(i64::from_ne_bytes(n), PhantomData)
535 }
536
537 /// Construct a new value given a native endian value.
538 pub fn new(e: E, n: i64) -> Self {
539 Self(e.write_i64(n), PhantomData)
540 }
541 /// Return the value as a native endian value.
542 pub fn get(self, e: E) -> i64 {
543 e.read_i64(self.0)
544 }
545 /// Set the value given a native endian value.
546 pub fn set(&mut self, e: E, n: i64) {
547 self.0 = e.write_i64(n);
548 }
549 }
550
551 impl<E: Endian> fmt::Debug for U16<E> {
552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553 write!(f, "U16({:x})", self.0)
554 }
555 }
556
557 impl<E: Endian> fmt::Debug for U32<E> {
558 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
559 write!(f, "U32({:x})", self.0)
560 }
561 }
562
563 impl<E: Endian> fmt::Debug for U64<E> {
564 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
565 write!(f, "U64({:x})", self.0)
566 }
567 }
568
569 impl<E: Endian> fmt::Debug for I16<E> {
570 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
571 write!(f, "I16({:x})", self.0)
572 }
573 }
574
575 impl<E: Endian> fmt::Debug for I32<E> {
576 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
577 write!(f, "I32({:x})", self.0)
578 }
579 }
580
581 impl<E: Endian> fmt::Debug for I64<E> {
582 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
583 write!(f, "I64({:x})", self.0)
584 }
585 }
586
587 unsafe_impl_endian_pod!(U16, U32, U64, I16, I32, I64);
588}
589
590#[cfg(not(feature = "unaligned"))]
591pub use aligned::*;
592
593/// A `u16` value with an externally specified endianness of type `E`.
594#[cfg(feature = "unaligned")]
595pub type U16<E> = U16Bytes<E>;
596
597/// A `u32` value with an externally specified endianness of type `E`.
598#[cfg(feature = "unaligned")]
599pub type U32<E> = U32Bytes<E>;
600
601/// A `u64` value with an externally specified endianness of type `E`.
602#[cfg(feature = "unaligned")]
603pub type U64<E> = U64Bytes<E>;
604
605/// An `i16` value with an externally specified endianness of type `E`.
606#[cfg(feature = "unaligned")]
607pub type I16<E> = I16Bytes<E>;
608
609/// An `i32` value with an externally specified endianness of type `E`.
610#[cfg(feature = "unaligned")]
611pub type I32<E> = I32Bytes<E>;
612
613/// An `i64` value with an externally specified endianness of type `E`.
614#[cfg(feature = "unaligned")]
615pub type I64<E> = I64Bytes<E>;
616
617/// An unaligned `u16` value with an externally specified endianness of type `E`.
618#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
619#[repr(transparent)]
620pub struct U16Bytes<E: Endian>([u8; 2], PhantomData<E>);
621
622impl<E: Endian> U16Bytes<E> {
623 /// Construct a new value given bytes that already have the required endianness.
624 pub fn from_bytes(n: [u8; 2]) -> Self {
625 Self(n, PhantomData)
626 }
627
628 /// Construct a new value given a native endian value.
629 pub fn new(e: E, n: u16) -> Self {
630 Self(e.write_u16_bytes(n), PhantomData)
631 }
632
633 /// Return the value as a native endian value.
634 pub fn get(self, e: E) -> u16 {
635 e.read_u16_bytes(self.0)
636 }
637
638 /// Set the value given a native endian value.
639 pub fn set(&mut self, e: E, n: u16) {
640 self.0 = e.write_u16_bytes(n);
641 }
642}
643
644/// An unaligned `u32` value with an externally specified endianness of type `E`.
645#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
646#[repr(transparent)]
647pub struct U32Bytes<E: Endian>([u8; 4], PhantomData<E>);
648
649impl<E: Endian> U32Bytes<E> {
650 /// Construct a new value given bytes that already have the required endianness.
651 pub fn from_bytes(n: [u8; 4]) -> Self {
652 Self(n, PhantomData)
653 }
654
655 /// Construct a new value given a native endian value.
656 pub fn new(e: E, n: u32) -> Self {
657 Self(e.write_u32_bytes(n), PhantomData)
658 }
659
660 /// Return the value as a native endian value.
661 pub fn get(self, e: E) -> u32 {
662 e.read_u32_bytes(self.0)
663 }
664
665 /// Set the value given a native endian value.
666 pub fn set(&mut self, e: E, n: u32) {
667 self.0 = e.write_u32_bytes(n);
668 }
669}
670
671/// An unaligned `u64` value with an externally specified endianness of type `E`.
672#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
673#[repr(transparent)]
674pub struct U64Bytes<E: Endian>([u8; 8], PhantomData<E>);
675
676impl<E: Endian> U64Bytes<E> {
677 /// Construct a new value given bytes that already have the required endianness.
678 pub fn from_bytes(n: [u8; 8]) -> Self {
679 Self(n, PhantomData)
680 }
681
682 /// Construct a new value given a native endian value.
683 pub fn new(e: E, n: u64) -> Self {
684 Self(e.write_u64_bytes(n), PhantomData)
685 }
686
687 /// Return the value as a native endian value.
688 pub fn get(self, e: E) -> u64 {
689 e.read_u64_bytes(self.0)
690 }
691
692 /// Set the value given a native endian value.
693 pub fn set(&mut self, e: E, n: u64) {
694 self.0 = e.write_u64_bytes(n);
695 }
696}
697
698/// An unaligned `i16` value with an externally specified endianness of type `E`.
699#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
700#[repr(transparent)]
701pub struct I16Bytes<E: Endian>([u8; 2], PhantomData<E>);
702
703impl<E: Endian> I16Bytes<E> {
704 /// Construct a new value given bytes that already have the required endianness.
705 pub fn from_bytes(n: [u8; 2]) -> Self {
706 Self(n, PhantomData)
707 }
708
709 /// Construct a new value given a native endian value.
710 pub fn new(e: E, n: i16) -> Self {
711 Self(e.write_i16_bytes(n), PhantomData)
712 }
713
714 /// Return the value as a native endian value.
715 pub fn get(self, e: E) -> i16 {
716 e.read_i16_bytes(self.0)
717 }
718
719 /// Set the value given a native endian value.
720 pub fn set(&mut self, e: E, n: i16) {
721 self.0 = e.write_i16_bytes(n);
722 }
723}
724
725/// An unaligned `i32` value with an externally specified endianness of type `E`.
726#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
727#[repr(transparent)]
728pub struct I32Bytes<E: Endian>([u8; 4], PhantomData<E>);
729
730impl<E: Endian> I32Bytes<E> {
731 /// Construct a new value given bytes that already have the required endianness.
732 pub fn from_bytes(n: [u8; 4]) -> Self {
733 Self(n, PhantomData)
734 }
735
736 /// Construct a new value given a native endian value.
737 pub fn new(e: E, n: i32) -> Self {
738 Self(e.write_i32_bytes(n), PhantomData)
739 }
740
741 /// Return the value as a native endian value.
742 pub fn get(self, e: E) -> i32 {
743 e.read_i32_bytes(self.0)
744 }
745
746 /// Set the value given a native endian value.
747 pub fn set(&mut self, e: E, n: i32) {
748 self.0 = e.write_i32_bytes(n);
749 }
750}
751
752/// An unaligned `i64` value with an externally specified endianness of type `E`.
753#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
754#[repr(transparent)]
755pub struct I64Bytes<E: Endian>([u8; 8], PhantomData<E>);
756
757impl<E: Endian> I64Bytes<E> {
758 /// Construct a new value given bytes that already have the required endianness.
759 pub fn from_bytes(n: [u8; 8]) -> Self {
760 Self(n, PhantomData)
761 }
762
763 /// Construct a new value given a native endian value.
764 pub fn new(e: E, n: i64) -> Self {
765 Self(e.write_i64_bytes(n), PhantomData)
766 }
767
768 /// Return the value as a native endian value.
769 pub fn get(self, e: E) -> i64 {
770 e.read_i64_bytes(self.0)
771 }
772
773 /// Set the value given a native endian value.
774 pub fn set(&mut self, e: E, n: i64) {
775 self.0 = e.write_i64_bytes(n);
776 }
777}
778
779impl<E: Endian> fmt::Debug for U16Bytes<E> {
780 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
781 write!(f, "U16({:x}, {:x})", self.0[0], self.0[1],)
782 }
783}
784
785impl<E: Endian> fmt::Debug for U32Bytes<E> {
786 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
787 write!(
788 f,
789 "U32({:x}, {:x}, {:x}, {:x})",
790 self.0[0], self.0[1], self.0[2], self.0[3],
791 )
792 }
793}
794
795impl<E: Endian> fmt::Debug for U64Bytes<E> {
796 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
797 write!(
798 f,
799 "U64({:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x})",
800 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7],
801 )
802 }
803}
804
805impl<E: Endian> fmt::Debug for I16Bytes<E> {
806 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
807 write!(f, "I16({:x}, {:x})", self.0[0], self.0[1],)
808 }
809}
810
811impl<E: Endian> fmt::Debug for I32Bytes<E> {
812 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
813 write!(
814 f,
815 "I32({:x}, {:x}, {:x}, {:x})",
816 self.0[0], self.0[1], self.0[2], self.0[3],
817 )
818 }
819}
820
821impl<E: Endian> fmt::Debug for I64Bytes<E> {
822 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
823 write!(
824 f,
825 "I64({:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x})",
826 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7],
827 )
828 }
829}
830
831unsafe_impl_endian_pod!(U16Bytes, U32Bytes, U64Bytes, I16Bytes, I32Bytes, I64Bytes);
832