use std::io::{Result as IoResult, Write};
use byteorder::{BigEndian, ByteOrder, LittleEndian, WriteBytesExt};
pub trait PackTo: Sized + Copy {
fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()>;
fn pack_to_be<W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
self.pack_to::<BigEndian, _>(dst)
}
fn pack_to_le<W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
self.pack_to::<LittleEndian, _>(dst)
}
fn pack_multiple_to<E: ByteOrder, W: Write + ?Sized>(
buf: &[Self],
dst: &mut W,
) -> IoResult<()> {
for i in buf {
i.pack_to::<E, _>(dst)?;
}
Ok(())
}
}
macro_rules! impl_tuple {
($($n:tt => $t:ident),+) => {
impl<$($t: PackTo),+> PackTo for ($($t,)+)
{
#[inline]
fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
$(self.$n.pack_to::<E, _>(dst)?;)+
Ok(())
}
}
};
}
impl_tuple!(0 => T1);
impl_tuple!(0 => T1, 1 => T2);
impl_tuple!(0 => T1, 1 => T2, 2 => T3);
impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4);
impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5);
impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6);
impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7);
impl_tuple!(0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8);
impl_tuple!(
0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6,
6 => T7, 7 => T8, 8 => T9
);
impl_tuple!(
0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6,
6 => T7, 7 => T8, 8 => T9, 9 => T10
);
impl_tuple!(
0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6,
6 => T7, 7 => T8, 8 => T9, 9 => T10, 10 => T11
);
impl_tuple!(
0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6,
6 => T7, 7 => T8, 8 => T9, 9 => T10, 10 => T11, 11 => T12
);
macro_rules! impl_primitive {
($($name:ident => $ty:ty),+) => {
$(
impl PackTo for $ty {
fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, src: &mut W) -> IoResult<()> {
src.$name::<E>(self)
}
}
)+
};
}
impl_primitive!(
write_u16 => u16, write_u32 => u32, write_u64 => u64, write_u128 => u128,
write_i16 => i16, write_i32 => i32, write_i64 => i64, write_i128 => i128,
write_f32 => f32, write_f64 => f64
);
impl PackTo for u8 {
fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
dst.write_u8(self)
}
fn pack_multiple_to<E: ByteOrder, W: Write + ?Sized>(
buf: &[Self],
dst: &mut W,
) -> IoResult<()> {
dst.write_all(buf)?;
Ok(())
}
}
impl PackTo for i8 {
fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
dst.write_i8(self)
}
}
impl<T: PackTo + Copy, const N: usize> PackTo for [T; N] {
fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
T::pack_multiple_to::<E, _>(&self[..], dst)?;
Ok(())
}
}
impl<T: PackTo + Copy> PackTo for &[T] {
fn pack_to<E: ByteOrder, W: Write + ?Sized>(self, dst: &mut W) -> IoResult<()> {
T::pack_multiple_to::<E, _>(self, dst)?;
Ok(())
}
}