1 //! Types for compile-time and run-time endianness.
4 use core
::fmt
::{self, Debug}
;
5 use core
::marker
::PhantomData
;
7 /// A trait for using an endianness specification.
9 /// Provides methods for converting between the specified endianness and
10 /// the native endianness of the target machine.
12 /// This trait does not require that the endianness is known at compile time.
13 pub trait Endian
: Debug
+ Default
+ Clone
+ Copy
+ PartialEq
+ Eq
+ '
static {
14 /// Construct a specification for the endianness of some values.
16 /// Returns `None` if the type does not support specifying the given endianness.
17 fn from_big_endian(big_endian
: bool
) -> Option
<Self>;
19 /// Construct a specification for the endianness of some values.
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
)
26 /// Return true for big endian byte order.
27 fn is_big_endian(self) -> bool
;
29 /// Return true for little endian byte order.
31 fn is_little_endian(self) -> bool
{
35 /// Converts an unsigned 16 bit integer to native endian.
37 fn read_u16(self, n
: u16) -> u16 {
38 if self.is_big_endian() {
45 /// Converts an unsigned 32 bit integer to native endian.
47 fn read_u32(self, n
: u32) -> u32 {
48 if self.is_big_endian() {
55 /// Converts an unsigned 64 bit integer to native endian.
57 fn read_u64(self, n
: u64) -> u64 {
58 if self.is_big_endian() {
65 /// Converts a signed 16 bit integer to native endian.
67 fn read_i16(self, n
: i16) -> i16 {
68 if self.is_big_endian() {
75 /// Converts a signed 32 bit integer to native endian.
77 fn read_i32(self, n
: i32) -> i32 {
78 if self.is_big_endian() {
85 /// Converts a signed 64 bit integer to native endian.
87 fn read_i64(self, n
: i64) -> i64 {
88 if self.is_big_endian() {
95 /// Converts an unaligned unsigned 16 bit integer to native endian.
97 fn read_u16_bytes(self, n
: [u8; 2]) -> u16 {
98 if self.is_big_endian() {
101 u16::from_le_bytes(n
)
105 /// Converts an unaligned unsigned 32 bit integer to native endian.
107 fn read_u32_bytes(self, n
: [u8; 4]) -> u32 {
108 if self.is_big_endian() {
109 u32::from_be_bytes(n
)
111 u32::from_le_bytes(n
)
115 /// Converts an unaligned unsigned 64 bit integer to native endian.
117 fn read_u64_bytes(self, n
: [u8; 8]) -> u64 {
118 if self.is_big_endian() {
119 u64::from_be_bytes(n
)
121 u64::from_le_bytes(n
)
125 /// Converts an unaligned signed 16 bit integer to native endian.
127 fn read_i16_bytes(self, n
: [u8; 2]) -> i16 {
128 if self.is_big_endian() {
129 i16::from_be_bytes(n
)
131 i16::from_le_bytes(n
)
135 /// Converts an unaligned signed 32 bit integer to native endian.
137 fn read_i32_bytes(self, n
: [u8; 4]) -> i32 {
138 if self.is_big_endian() {
139 i32::from_be_bytes(n
)
141 i32::from_le_bytes(n
)
145 /// Converts an unaligned signed 64 bit integer to native endian.
147 fn read_i64_bytes(self, n
: [u8; 8]) -> i64 {
148 if self.is_big_endian() {
149 i64::from_be_bytes(n
)
151 i64::from_le_bytes(n
)
155 /// Converts an unsigned 16 bit integer from native endian.
157 fn write_u16(self, n
: u16) -> u16 {
158 if self.is_big_endian() {
165 /// Converts an unsigned 32 bit integer from native endian.
167 fn write_u32(self, n
: u32) -> u32 {
168 if self.is_big_endian() {
175 /// Converts an unsigned 64 bit integer from native endian.
177 fn write_u64(self, n
: u64) -> u64 {
178 if self.is_big_endian() {
185 /// Converts a signed 16 bit integer from native endian.
187 fn write_i16(self, n
: i16) -> i16 {
188 if self.is_big_endian() {
195 /// Converts a signed 32 bit integer from native endian.
197 fn write_i32(self, n
: i32) -> i32 {
198 if self.is_big_endian() {
205 /// Converts a signed 64 bit integer from native endian.
207 fn write_i64(self, n
: i64) -> i64 {
208 if self.is_big_endian() {
215 /// Converts an unaligned unsigned 16 bit integer from native endian.
217 fn write_u16_bytes(self, n
: u16) -> [u8; 2] {
218 if self.is_big_endian() {
225 /// Converts an unaligned unsigned 32 bit integer from native endian.
227 fn write_u32_bytes(self, n
: u32) -> [u8; 4] {
228 if self.is_big_endian() {
235 /// Converts an unaligned unsigned 64 bit integer from native endian.
237 fn write_u64_bytes(self, n
: u64) -> [u8; 8] {
238 if self.is_big_endian() {
245 /// Converts an unaligned signed 16 bit integer from native endian.
247 fn write_i16_bytes(self, n
: i16) -> [u8; 2] {
248 if self.is_big_endian() {
255 /// Converts an unaligned signed 32 bit integer from native endian.
257 fn write_i32_bytes(self, n
: i32) -> [u8; 4] {
258 if self.is_big_endian() {
265 /// Converts an unaligned signed 64 bit integer from native endian.
267 fn write_i64_bytes(self, n
: i64) -> [u8; 8] {
268 if self.is_big_endian() {
276 /// An endianness that is selectable at run-time.
277 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
278 pub enum Endianness
{
279 /// Little endian byte order.
281 /// Big endian byte order.
285 impl Default
for Endianness
{
286 #[cfg(target_endian = "little")]
288 fn default() -> Endianness
{
292 #[cfg(target_endian = "big")]
294 fn default() -> Endianness
{
299 impl Endian
for Endianness
{
301 fn from_big_endian(big_endian
: bool
) -> Option
<Self> {
310 fn is_big_endian(self) -> bool
{
311 self != Endianness
::Little
315 /// Compile-time little endian byte order.
316 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
317 pub struct LittleEndian
;
319 impl Default
for LittleEndian
{
321 fn default() -> LittleEndian
{
326 impl Endian
for LittleEndian
{
328 fn from_big_endian(big_endian
: bool
) -> Option
<Self> {
337 fn is_big_endian(self) -> bool
{
342 /// Compile-time big endian byte order.
343 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
344 pub struct BigEndian
;
346 impl Default
for BigEndian
{
348 fn default() -> BigEndian
{
353 impl Endian
for BigEndian
{
355 fn from_big_endian(big_endian
: bool
) -> Option
<Self> {
364 fn is_big_endian(self) -> bool
{
369 /// The native endianness for the target platform.
370 #[cfg(target_endian = "little")]
371 pub type NativeEndian
= LittleEndian
;
373 #[cfg(target_endian = "little")]
374 #[allow(non_upper_case_globals)]
376 pub const NativeEndian
: LittleEndian
= LittleEndian
;
378 /// The native endianness for the target platform.
379 #[cfg(target_endian = "big")]
380 pub type NativeEndian
= BigEndian
;
382 #[cfg(target_endian = "big")]
383 #[allow(non_upper_case_globals)]
385 pub const NativeEndian
: BigEndian
= BigEndian
;
387 macro_rules
! unsafe_impl_endian_pod
{
388 ($
($struct_name
:ident
),+ $
(,)?
) => {
390 unsafe impl<E
: Endian
> Pod
for $struct_name
<E
> { }
395 #[cfg(not(feature = "unaligned"))]
397 use super::{fmt, Endian, PhantomData, Pod}
;
399 /// A `u16` value with an externally specified endianness of type `E`.
400 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
402 pub struct U16
<E
: Endian
>(u16, PhantomData
<E
>);
404 impl<E
: Endian
> U16
<E
> {
405 /// Construct a new value given a native endian value.
406 pub fn new(e
: E
, n
: u16) -> Self {
407 Self(e
.write_u16(n
), PhantomData
)
410 /// Return the value as a native endian value.
411 pub fn get(self, e
: E
) -> u16 {
415 /// Set the value given a native endian value.
416 pub fn set(&mut self, e
: E
, n
: u16) {
417 self.0 = e
.write_u16(n
);
421 /// A `u32` value with an externally specified endianness of type `E`.
422 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
424 pub struct U32
<E
: Endian
>(u32, PhantomData
<E
>);
426 impl<E
: Endian
> U32
<E
> {
427 /// Construct a new value given a native endian value.
428 pub fn new(e
: E
, n
: u32) -> Self {
429 Self(e
.write_u32(n
), PhantomData
)
431 /// Return the value as a native endian value.
432 pub fn get(self, e
: E
) -> u32 {
435 /// Set the value given a native endian value.
436 pub fn set(&mut self, e
: E
, n
: u32) {
437 self.0 = e
.write_u32(n
);
441 /// A `u64` value with an externally specified endianness of type `E`.
442 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
444 pub struct U64
<E
: Endian
>(u64, PhantomData
<E
>);
446 impl<E
: Endian
> U64
<E
> {
447 /// Construct a new value given a native endian value.
448 pub fn new(e
: E
, n
: u64) -> Self {
449 Self(e
.write_u64(n
), PhantomData
)
451 /// Return the value as a native endian value.
452 pub fn get(self, e
: E
) -> u64 {
455 /// Set the value given a native endian value.
456 pub fn set(&mut self, e
: E
, n
: u64) {
457 self.0 = e
.write_u64(n
);
461 /// An `i16` value with an externally specified endianness of type `E`.
462 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
464 pub struct I16
<E
: Endian
>(i16, PhantomData
<E
>);
466 impl<E
: Endian
> I16
<E
> {
467 /// Construct a new value given a native endian value.
468 pub fn new(e
: E
, n
: i16) -> Self {
469 Self(e
.write_i16(n
), PhantomData
)
471 /// Return the value as a native endian value.
472 pub fn get(self, e
: E
) -> i16 {
475 /// Set the value given a native endian value.
476 pub fn set(&mut self, e
: E
, n
: i16) {
477 self.0 = e
.write_i16(n
);
481 /// An `i32` value with an externally specified endianness of type `E`.
482 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
484 pub struct I32
<E
: Endian
>(i32, PhantomData
<E
>);
486 impl<E
: Endian
> I32
<E
> {
487 /// Construct a new value given a native endian value.
488 pub fn new(e
: E
, n
: i32) -> Self {
489 Self(e
.write_i32(n
), PhantomData
)
491 /// Return the value as a native endian value.
492 pub fn get(self, e
: E
) -> i32 {
495 /// Set the value given a native endian value.
496 pub fn set(&mut self, e
: E
, n
: i32) {
497 self.0 = e
.write_i32(n
);
501 /// An `i64` value with an externally specified endianness of type `E`.
502 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
504 pub struct I64
<E
: Endian
>(i64, PhantomData
<E
>);
506 impl<E
: Endian
> I64
<E
> {
507 /// Construct a new value given a native endian value.
508 pub fn new(e
: E
, n
: i64) -> Self {
509 Self(e
.write_i64(n
), PhantomData
)
511 /// Return the value as a native endian value.
512 pub fn get(self, e
: E
) -> i64 {
515 /// Set the value given a native endian value.
516 pub fn set(&mut self, e
: E
, n
: i64) {
517 self.0 = e
.write_i64(n
);
521 impl<E
: Endian
> fmt
::Debug
for U16
<E
> {
522 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
523 write
!(f
, "U16({:x})", self.0)
527 impl<E
: Endian
> fmt
::Debug
for U32
<E
> {
528 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
529 write
!(f
, "U32({:x})", self.0)
533 impl<E
: Endian
> fmt
::Debug
for U64
<E
> {
534 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
535 write
!(f
, "U64({:x})", self.0)
539 impl<E
: Endian
> fmt
::Debug
for I16
<E
> {
540 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
541 write
!(f
, "I16({:x})", self.0)
545 impl<E
: Endian
> fmt
::Debug
for I32
<E
> {
546 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
547 write
!(f
, "I32({:x})", self.0)
551 impl<E
: Endian
> fmt
::Debug
for I64
<E
> {
552 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
553 write
!(f
, "I64({:x})", self.0)
557 unsafe_impl_endian_pod
!(U16
, U32
, U64
, I16
, I32
, I64
);
560 #[cfg(not(feature = "unaligned"))]
563 /// A `u16` value with an externally specified endianness of type `E`.
564 #[cfg(feature = "unaligned")]
565 pub type U16
<E
> = U16Bytes
<E
>;
567 /// A `u32` value with an externally specified endianness of type `E`.
568 #[cfg(feature = "unaligned")]
569 pub type U32
<E
> = U32Bytes
<E
>;
571 /// A `u64` value with an externally specified endianness of type `E`.
572 #[cfg(feature = "unaligned")]
573 pub type U64
<E
> = U64Bytes
<E
>;
575 /// An `i16` value with an externally specified endianness of type `E`.
576 #[cfg(feature = "unaligned")]
577 pub type I16
<E
> = I16Bytes
<E
>;
579 /// An `i32` value with an externally specified endianness of type `E`.
580 #[cfg(feature = "unaligned")]
581 pub type I32
<E
> = I32Bytes
<E
>;
583 /// An `i64` value with an externally specified endianness of type `E`.
584 #[cfg(feature = "unaligned")]
585 pub type I64
<E
> = I64Bytes
<E
>;
587 /// An unaligned `u16` value with an externally specified endianness of type `E`.
588 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
590 pub struct U16Bytes
<E
: Endian
>([u8; 2], PhantomData
<E
>);
592 impl<E
: Endian
> U16Bytes
<E
> {
593 /// Construct a new value given a native endian value.
594 pub fn new(e
: E
, n
: u16) -> Self {
595 Self(e
.write_u16_bytes(n
), PhantomData
)
598 /// Return the value as a native endian value.
599 pub fn get(self, e
: E
) -> u16 {
600 e
.read_u16_bytes(self.0)
603 /// Set the value given a native endian value.
604 pub fn set(&mut self, e
: E
, n
: u16) {
605 self.0 = e
.write_u16_bytes(n
);
609 /// An unaligned `u32` value with an externally specified endianness of type `E`.
610 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
612 pub struct U32Bytes
<E
: Endian
>([u8; 4], PhantomData
<E
>);
614 impl<E
: Endian
> U32Bytes
<E
> {
615 /// Construct a new value given a native endian value.
616 pub fn new(e
: E
, n
: u32) -> Self {
617 Self(e
.write_u32_bytes(n
), PhantomData
)
620 /// Return the value as a native endian value.
621 pub fn get(self, e
: E
) -> u32 {
622 e
.read_u32_bytes(self.0)
625 /// Set the value given a native endian value.
626 pub fn set(&mut self, e
: E
, n
: u32) {
627 self.0 = e
.write_u32_bytes(n
);
631 /// An unaligned `u64` value with an externally specified endianness of type `E`.
632 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
634 pub struct U64Bytes
<E
: Endian
>([u8; 8], PhantomData
<E
>);
636 impl<E
: Endian
> U64Bytes
<E
> {
637 /// Construct a new value given a native endian value.
638 pub fn new(e
: E
, n
: u64) -> Self {
639 Self(e
.write_u64_bytes(n
), PhantomData
)
642 /// Return the value as a native endian value.
643 pub fn get(self, e
: E
) -> u64 {
644 e
.read_u64_bytes(self.0)
647 /// Set the value given a native endian value.
648 pub fn set(&mut self, e
: E
, n
: u64) {
649 self.0 = e
.write_u64_bytes(n
);
653 /// An unaligned `i16` value with an externally specified endianness of type `E`.
654 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
656 pub struct I16Bytes
<E
: Endian
>([u8; 2], PhantomData
<E
>);
658 impl<E
: Endian
> I16Bytes
<E
> {
659 /// Construct a new value given a native endian value.
660 pub fn new(e
: E
, n
: i16) -> Self {
661 Self(e
.write_i16_bytes(n
), PhantomData
)
664 /// Return the value as a native endian value.
665 pub fn get(self, e
: E
) -> i16 {
666 e
.read_i16_bytes(self.0)
669 /// Set the value given a native endian value.
670 pub fn set(&mut self, e
: E
, n
: i16) {
671 self.0 = e
.write_i16_bytes(n
);
675 /// An unaligned `i32` value with an externally specified endianness of type `E`.
676 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
678 pub struct I32Bytes
<E
: Endian
>([u8; 4], PhantomData
<E
>);
680 impl<E
: Endian
> I32Bytes
<E
> {
681 /// Construct a new value given a native endian value.
682 pub fn new(e
: E
, n
: i32) -> Self {
683 Self(e
.write_i32_bytes(n
), PhantomData
)
686 /// Return the value as a native endian value.
687 pub fn get(self, e
: E
) -> i32 {
688 e
.read_i32_bytes(self.0)
691 /// Set the value given a native endian value.
692 pub fn set(&mut self, e
: E
, n
: i32) {
693 self.0 = e
.write_i32_bytes(n
);
697 /// An unaligned `i64` value with an externally specified endianness of type `E`.
698 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
700 pub struct I64Bytes
<E
: Endian
>([u8; 8], PhantomData
<E
>);
702 impl<E
: Endian
> I64Bytes
<E
> {
703 /// Construct a new value given a native endian value.
704 pub fn new(e
: E
, n
: i64) -> Self {
705 Self(e
.write_i64_bytes(n
), PhantomData
)
708 /// Return the value as a native endian value.
709 pub fn get(self, e
: E
) -> i64 {
710 e
.read_i64_bytes(self.0)
713 /// Set the value given a native endian value.
714 pub fn set(&mut self, e
: E
, n
: i64) {
715 self.0 = e
.write_i64_bytes(n
);
719 impl<E
: Endian
> fmt
::Debug
for U16Bytes
<E
> {
720 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
721 write
!(f
, "U16({:x}, {:x})", self.0[0], self.0[1],)
725 impl<E
: Endian
> fmt
::Debug
for U32Bytes
<E
> {
726 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
729 "U32({:x}, {:x}, {:x}, {:x})",
730 self.0[0], self.0[1], self.0[2], self.0[3],
735 impl<E
: Endian
> fmt
::Debug
for U64Bytes
<E
> {
736 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
739 "U64({:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x})",
740 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7],
745 impl<E
: Endian
> fmt
::Debug
for I16Bytes
<E
> {
746 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
747 write
!(f
, "I16({:x}, {:x})", self.0[0], self.0[1],)
751 impl<E
: Endian
> fmt
::Debug
for I32Bytes
<E
> {
752 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
755 "I32({:x}, {:x}, {:x}, {:x})",
756 self.0[0], self.0[1], self.0[2], self.0[3],
761 impl<E
: Endian
> fmt
::Debug
for I64Bytes
<E
> {
762 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
765 "I64({:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x})",
766 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7],
771 unsafe_impl_endian_pod
!(U16Bytes
, U32Bytes
, U64Bytes
, I16Bytes
, I32Bytes
, I64Bytes
);