1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::convert::TryInto;

use super::{Dump, FrameReader, FrameTarget, FrameWriter, Grab};

macro_rules! impl_for_numeric {
    ($size:literal, $t:ty) => {
        impl Dump for $t {
            fn dump_to<T: FrameTarget>(&self, writer: &mut FrameWriter<T>) {
                let bytes = self.to_be_bytes();
                writer.write_bytes(&bytes[..]);
            }
        }

        impl<'a> Grab<'a> for $t {
            fn grab_from(reader: &mut FrameReader<'a>) -> Option<Self> {
                reader
                    .read_bytes($size)
                    .map(|bytes| Self::from_be_bytes(bytes.try_into().unwrap()))
            }
        }
    };
}

macro_rules! impl_for_numeric_multi {
    ($(($size:literal, $t:ty),)*) => {
        $( impl_for_numeric!($size, $t); )*
    }
}

macro_rules! impl_for_tuple {
    ($($v:ident $t:ident),*) => {
        impl < $($t : Dump),* > Dump for ($($t,)*) {
            #[allow(unused_parens)]
            #[allow(unused_variables)]
            fn dump_to<T: FrameTarget>(&self, writer: &mut FrameWriter<T>) {
                let ($($v),*) = self;
                $(
                    writer.write($v);
                )*
            }
        }

        impl < 'a, $($t : Grab<'a> ),*> Grab<'a> for ($($t,)*) {
            #[allow(unused_variables)]
            fn grab_from(reader: &mut FrameReader<'a>) -> Option<Self> {
                $(
                    let $v = reader.read()?;
                )*
                Some(($(
                    $v
                ),*))
            }
        }
    }
}

macro_rules! impl_for_tuple_multi {
    ($($args:tt,)*) => {
        $( impl_for_tuple! $args; )*
    }
}

impl<'a, A: Dump> Dump for &'a A {
    fn dump_to<T: FrameTarget>(&self, writer: &mut FrameWriter<T>) {
        (**self).dump_to(writer);
    }
}

impl<'a, A: Dump> Dump for &'a mut A {
    fn dump_to<T: FrameTarget>(&self, writer: &mut FrameWriter<T>) {
        (**self).dump_to(writer);
    }
}

impl Dump for bool {
    fn dump_to<T: FrameTarget>(&self, writer: &mut FrameWriter<T>) {
        writer.write(if *self { 1u8 } else { 0u8 }); // TODO: write one bit
    }
}

impl<'a> Grab<'a> for bool {
    fn grab_from(reader: &mut FrameReader<'a>) -> Option<Self> {
        let me: u8 = reader.read()?;
        Some(me != 0)
    }
}

impl_for_numeric_multi! {
    (1, u8 ),
    (2, u16),
    (4, u32),
    (8, u64),
    (1, i8 ),
    (2, i16),
    (4, i32),
    (8, i64),
    (4, f32),
    (8, f64),
}

impl_for_tuple_multi! {
    (),
    (a A),
    (a A, b B),
    (a A, b B, c C),
    (a A, b B, c C, d D),
    (a A, b B, c C, d D, e E),
    (a A, b B, c C, d D, e E, f F),
    (a A, b B, c C, d D, e E, f F, g G),
    (a A, b B, c C, d D, e E, f F, g G, h H),
    (a A, b B, c C, d D, e E, f F, g G, h H, i I),
    (a A, b B, c C, d D, e E, f F, g G, h H, i I, j J),
}