Skip to main content

futures_byteorder/
traits.rs

1use std::borrow::{Borrow, BorrowMut};
2
3use crate::{BigEndian, LittleEndian};
4
5pub trait Sealed {}
6
7pub trait ByteArray: Sealed + Default + Borrow<[u8]> + BorrowMut<[u8]> + Copy {}
8
9/// A trait defining byte order conversion behavior.
10///
11/// This trait is implemented by [`BigEndian`], [`LittleEndian`], and their type aliases
12/// to define how numeric values should be converted to and from byte representations.
13///
14/// # Examples
15///
16/// ```
17/// use futures_byteorder::{Endianness, BigEndian, Representable};
18///
19/// let value: u16 = 0x1234;
20/// let bytes = BigEndian::from_representable(&value);
21/// assert_eq!(bytes, [0x12, 0x34]);
22///
23/// let decoded = BigEndian::to_representable::<u16>(&bytes);
24/// assert_eq!(decoded, 0x1234);
25/// ```
26pub trait Endianness: Sealed {
27    /// Converts a representable value to its byte representation using this endianness.
28    ///
29    /// # Examples
30    ///
31    /// ```
32    /// use futures_byteorder::{Endianness, LittleEndian};
33    ///
34    /// let value: u32 = 0x12345678;
35    /// let bytes = LittleEndian::from_representable(&value);
36    /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
37    /// ```
38    fn from_representable<R: Representable>(representable: &R) -> R::Representation;
39
40    /// Converts a byte representation to a representable value using this endianness.
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use futures_byteorder::{Endianness, BigEndian};
46    ///
47    /// let bytes = [0x12, 0x34, 0x56, 0x78];
48    /// let value = BigEndian::to_representable::<u32>(&bytes);
49    /// assert_eq!(value, 0x12345678);
50    /// ```
51    fn to_representable<R: Representable>(representation: &R::Representation) -> R;
52}
53
54/// A trait for types that can be represented as a fixed-size byte array.
55///
56/// This trait is implemented for all primitive integer types (`u8`-`u128`, `i8`-`i128`)
57/// and floating-point types (`f32`, `f64`). It provides methods for converting between
58/// the type and its byte representation in both little-endian and big-endian formats.
59///
60/// # Examples
61///
62/// ```
63/// use futures_byteorder::Representable;
64///
65/// let value: u16 = 0x1234;
66/// let le_bytes = value.to_le_bytes();
67/// let be_bytes = value.to_be_bytes();
68///
69/// assert_eq!(le_bytes, [0x34, 0x12]);
70/// assert_eq!(be_bytes, [0x12, 0x34]);
71///
72/// assert_eq!(u16::from_le_bytes(le_bytes), value);
73/// assert_eq!(u16::from_be_bytes(be_bytes), value);
74/// ```
75pub trait Representable {
76    /// The byte array type that represents this type.
77    ///
78    /// For example, `u16::Representation` is `[u8; 2]`, and `u64::Representation` is `[u8; 8]`.
79    type Representation: ByteArray;
80
81    /// Creates a value from its little-endian byte representation.
82    fn from_le_bytes(bytes: &Self::Representation) -> Self;
83
84    /// Creates a value from its big-endian byte representation
85    fn from_be_bytes(bytes: &Self::Representation) -> Self;
86
87    /// Returns the little-endian byte representation of this value.
88    fn to_le_bytes(&self) -> Self::Representation;
89
90    /// Returns the big-endian byte representation of this value.
91    fn to_be_bytes(&self) -> Self::Representation;
92}
93
94impl<const N: usize> Sealed for [u8; N] {}
95impl<const N: usize> ByteArray for [u8; N] where [u8; N]: Default + Borrow<[u8]> + BorrowMut<[u8]> {}
96
97impl Sealed for BigEndian {}
98impl Endianness for BigEndian {
99    fn from_representable<R: Representable>(representable: &R) -> R::Representation {
100        representable.to_be_bytes()
101    }
102
103    fn to_representable<R: Representable>(representation: &R::Representation) -> R {
104        R::from_be_bytes(representation)
105    }
106}
107
108impl Sealed for LittleEndian {}
109impl Endianness for LittleEndian {
110    fn from_representable<R: Representable>(representable: &R) -> R::Representation {
111        representable.to_le_bytes()
112    }
113
114    fn to_representable<R: Representable>(representation: &R::Representation) -> R {
115        R::from_le_bytes(representation)
116    }
117}
118
119macro_rules! impl_representable {
120    ($($num:ty),* $(,)?) => {
121        $(impl Representable for $num {
122            type Representation = [u8; std::mem::size_of::<$num>()];
123
124            fn from_le_bytes(bytes: &Self::Representation) -> Self {
125                Self::from_le_bytes(*bytes)
126            }
127
128            fn from_be_bytes(bytes: &Self::Representation) -> Self {
129                Self::from_be_bytes(*bytes)
130            }
131
132            fn to_le_bytes(&self) -> Self::Representation {
133                Self::to_le_bytes(*self)
134            }
135
136            fn to_be_bytes(&self) -> Self::Representation {
137                Self::to_be_bytes(*self)
138            }
139        })*
140    }
141}
142
143impl_representable!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);