1use std::io::{Result as IoResult, Write};
2
3use byteorder::{BigEndian, ByteOrder, LittleEndian, WriteBytesExt};
4
5pub trait PackTo: Sized + Copy {
7 fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()>;
21
22 fn pack_to_be<W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
35 self.pack_to::<BigEndian, _>(dst)
36 }
37 fn pack_to_le<W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
50 self.pack_to::<LittleEndian, _>(dst)
51 }
52
53 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}