write_into/
endianness.rs

1use super::{write_into, WriteInto};
2use std::io;
3use std::mem::size_of;
4
5/// Used to write values in big endian byte order.
6///
7/// # Example
8///
9/// ```
10/// use write_into::{BigEndian, write_into};
11///
12/// let mut buffer = Vec::new();
13/// write_into(&mut buffer, BigEndian(0xCAFEBABEu32)).unwrap();
14/// assert_eq!(&buffer, &[0xCA, 0xFE, 0xBA, 0xBE]);
15/// ```
16pub struct BigEndian<T>(pub T);
17
18/// Used to write values in little endian byte order.
19///
20/// # Example
21///
22/// ```
23/// use write_into::{LittleEndian, write_into};
24///
25/// let mut buffer = Vec::new();
26/// write_into(&mut buffer, LittleEndian(0xCAFEBABEu32)).unwrap();
27/// assert_eq!(&buffer, &[0xBE, 0xBA, 0xFE, 0xCA]);
28/// ```
29pub struct LittleEndian<T>(pub T);
30
31macro_rules! impl_write_into {
32    ($($wrapper:ident => { $($primitive:ident)* } ),*,) => {
33        $(
34            $(
35                impl WriteInto for $wrapper<$primitive> {
36                    type Output = ();
37
38                    fn write_into(self, sink: &mut impl io::Write) -> io::Result<Self::Output> {
39                        let bytes = convertion!($wrapper, self.0);
40                        sink.write_all(&bytes)?;
41                        Ok(())
42                    }
43                }
44
45                impl WriteInto for &$wrapper<$primitive> {
46                    type Output = ();
47
48                    fn write_into(self, sink: &mut impl io::Write) -> io::Result<Self::Output> {
49                        write_into(sink, $wrapper(self.0))
50                    }
51                }
52            )*
53        )*
54    };
55}
56
57macro_rules! convertion {
58    (BigEndian, $expr:expr) => {
59        ($expr).to_be_bytes()
60    };
61    (LittleEndian, $expr:expr) => {
62        ($expr).to_le_bytes()
63    };
64}
65
66impl_write_into! {
67    BigEndian => {
68        i8 i16 i32 i64 i128 isize
69        u8 u16 u32 u64 u128 usize
70        bool char f32 f64
71    },
72    LittleEndian => {
73        i8 i16 i32 i64 i128 isize
74        u8 u16 u32 u64 u128 usize
75        bool char f32 f64
76    },
77}
78
79trait EndiannessExts {
80    type Repr;
81    fn to_be_bytes(self) -> Self::Repr;
82    fn to_le_bytes(self) -> Self::Repr;
83}
84
85macro_rules! impl_endianness_exts {
86    ($($primitive:ident => $repr:ident),*,) => {
87        $(
88            impl EndiannessExts for $primitive {
89                type Repr = [u8; size_of::<Self>()];
90
91                fn to_be_bytes(self) -> Self::Repr {
92                    $repr::from(self).to_be_bytes()
93                }
94
95                fn to_le_bytes(self) -> Self::Repr {
96                    $repr::from(self).to_le_bytes()
97                }
98            } 
99        )*
100    };
101}
102
103impl_endianness_exts! {
104    char => u32,
105    bool => u8,
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111
112    #[test]
113    fn char_be() {
114        assert_eq!('\x7F'.to_be_bytes(), 0x7Fu32.to_be_bytes());
115    }
116    
117    #[test]
118    fn char_le() {
119        assert_eq!('\x7F'.to_le_bytes(), 0x7Fu32.to_le_bytes());
120    }
121}