byteorder_pack/
pack.rs

1use std::io::{Result as IoResult, Write};
2
3use byteorder::{BigEndian, ByteOrder, LittleEndian, WriteBytesExt};
4
5/// Write a value into a [`Write`].
6pub trait PackTo: Sized + Copy {
7    /// Pack binary data into `dst`.
8    /// # Example
9    /// ```rust
10    /// use std::io::Cursor;
11    /// use byteorder::BigEndian;
12    /// use byteorder_pack::PackTo;
13    ///
14    /// let mut cursor = Cursor::new(vec![]);
15    ///
16    /// (1u8, 2u8, 3u16, 4u16).pack_to::<BigEndian, _>(&mut cursor).unwrap();
17    ///
18    /// assert_eq!(cursor.into_inner(), vec![0x01, 0x02, 0x00, 0x03, 0x00, 0x04]);
19    /// ```
20    fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()>;
21
22    /// Pack binary data into `dst` from a tuple, in [`BigEndian`] order.
23    /// # Example
24    /// ```rust
25    /// use std::io::Cursor;
26    /// use byteorder_pack::PackTo;
27    ///
28    /// let mut cursor = Cursor::new(vec![]);
29    ///
30    /// (1u8, 2u8, 3u16, 4u16).pack_to_be(&mut cursor).unwrap();
31    ///
32    /// assert_eq!(cursor.into_inner(), vec![0x01, 0x02, 0x00, 0x03, 0x00, 0x04]);
33    /// ```
34    fn pack_to_be<W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
35        self.pack_to::<BigEndian, _>(dst)
36    }
37    /// Pack binary data into `dst` from a tuple, in [`LittleEndian`] order.
38    /// # Example
39    /// ```rust
40    /// use std::io::Cursor;
41    /// use byteorder_pack::PackTo;
42    ///
43    /// let mut cursor = Cursor::new(vec![]);
44    ///
45    /// (1u8, 2u8, 3u16, 4u16).pack_to_le(&mut cursor).unwrap();
46    ///
47    /// assert_eq!(cursor.into_inner(), vec![0x01, 0x02, 0x03, 0x00, 0x04, 0x00]);
48    /// ```
49    fn pack_to_le<W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
50        self.pack_to::<LittleEndian, _>(dst)
51    }
52
53    /// Pack multiple values into `dest`.
54    fn pack_multiple_to<E: ByteOrder, W: Write + ?Sized>(
55        buf: &[Self],
56        dst: &mut W,
57    ) -> IoResult<()> {
58        for i in buf {
59            i.pack_to::<E, _>(dst)?;
60        }
61        Ok(())
62    }
63}
64
65macro_rules! impl_tuple {
66    ($($n:tt => $t:ident),+) => {
67        impl<$($t: PackTo),+> PackTo for ($($t,)+)
68        {
69            #[inline]
70            fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
71                $(self.$n.pack_to::<E, _>(dst)?;)+
72                Ok(())
73            }
74        }
75    };
76}
77impl_tuple!(0 => T1);
78impl_tuple!(0 => T1, 1 => T2);
79impl_tuple!(0 => T1, 1 => T2, 2 => T3);
80impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4);
81impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5);
82impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6);
83impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7);
84impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8);
85impl_tuple!(
86    0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6,
87    6 => T7, 7 => T8, 8 => T9
88);
89impl_tuple!(
90    0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6,
91    6 => T7, 7 => T8, 8 => T9, 9 => T10
92);
93impl_tuple!(
94    0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6,
95    6 => T7, 7 => T8, 8 => T9, 9 => T10, 10 => T11
96);
97impl_tuple!(
98    0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6,
99    6 => T7, 7 => T8, 8 => T9, 9 => T10, 10 => T11, 11 => T12
100);
101
102macro_rules! impl_primitive {
103    ($($name:ident => $ty:ty),+) => {
104        $(
105            impl PackTo for $ty {
106                fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, src: &mut W) -> IoResult<()> {
107                    src.$name::<E>(self)
108                }
109            }
110        )+
111    };
112}
113
114impl_primitive!(
115    write_u16 => u16, write_u32 => u32, write_u64 => u64, write_u128 => u128,
116    write_i16 => i16, write_i32 => i32, write_i64 => i64, write_i128 => i128,
117    write_f32 => f32, write_f64 => f64
118);
119
120impl PackTo for u8 {
121    fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
122        dst.write_u8(self)
123    }
124
125    fn pack_multiple_to<E: ByteOrder, W: Write + ?Sized>(
126        buf: &[Self],
127        dst: &mut W,
128    ) -> IoResult<()> {
129        dst.write_all(buf)?;
130        Ok(())
131    }
132}
133
134impl PackTo for i8 {
135    fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
136        dst.write_i8(self)
137    }
138}
139
140impl<T: PackTo + Copy, const N: usize> PackTo for [T; N] {
141    fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
142        T::pack_multiple_to::<E, _>(&self[..], dst)?;
143        Ok(())
144    }
145}
146
147impl<T: PackTo + Copy> PackTo for &[T] {
148    fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
149        T::pack_multiple_to::<E, _>(self, dst)?;
150        Ok(())
151    }
152}