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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use std::io::{Read, Seek, SeekFrom};

use Result;

/// A type that can read.
pub trait Tape: Read + Seek + Sized {
    /// Read a value.
    #[inline(always)]
    fn take<T: Value>(&mut self) -> Result<T> {
        Value::read(self)
    }

    /// Read a value given a parameter.
    #[inline(always)]
    fn take_given<'l, T: Walue<'l>>(&mut self, parameter: T::Parameter) -> Result<T> {
        Walue::read(self, parameter)
    }

    #[doc(hidden)]
    #[inline]
    fn jump(&mut self, position: u64) -> Result<u64> {
        self.seek(SeekFrom::Start(position))
    }

    #[doc(hidden)]
    #[inline]
    fn peek<T: Value>(&mut self) -> Result<T> {
        self.stay(|tape| Value::read(tape))
    }

    #[doc(hidden)]
    #[inline]
    fn position(&mut self) -> Result<u64> {
        self.seek(SeekFrom::Current(0))
    }

    #[doc(hidden)]
    fn stay<F, T>(&mut self, mut body: F) -> Result<T>
    where
        F: FnMut(&mut Self) -> Result<T>,
    {
        let position = self.position()?;
        let result = body(self);
        self.jump(position)?;
        result
    }

    #[doc(hidden)]
    #[inline(always)]
    fn take_bytes(&mut self, count: usize) -> Result<Vec<u8>> {
        let mut buffer = Vec::with_capacity(count);
        unsafe { buffer.set_len(count) };
        self.read_exact(&mut buffer)?;
        Ok(buffer)
    }
}

/// A type that can be read.
pub trait Value: Sized {
    /// Read a value.
    fn read<T: Tape>(&mut T) -> Result<Self>;
}

/// A type that can be read given a parameter.
pub trait Walue<'l>: Sized {
    /// The parameter type.
    type Parameter;

    /// Read a value.
    fn read<T: Tape>(&mut T, Self::Parameter) -> Result<Self>;
}

impl<T: Read + Seek> Tape for T {}

macro_rules! read(
    ($tape:ident, $size:expr) => (unsafe {
        let mut buffer: [u8; $size] = ::std::mem::uninitialized();
        ::std::io::Read::read_exact($tape, &mut buffer)?;
        ::std::mem::transmute(buffer)
    });
);

macro_rules! value {
    ([$kind:ident; $count:expr], 1) => (
        impl Value for [$kind; $count] {
            fn read<T: Tape>(tape: &mut T) -> Result<Self> {
                Ok(read!(tape, $count))
            }
        }
    );
    ($kind:ident, 1) => (
        impl Value for $kind {
            #[inline]
            fn read<T: Tape>(tape: &mut T) -> Result<Self> {
                Ok(read!(tape, 1))
            }
        }
    );
    ($kind:ident, $size:expr) => (
        impl Value for $kind {
            #[inline]
            fn read<T: Tape>(tape: &mut T) -> Result<Self> {
                Ok($kind::from_be(read!(tape, $size)))
            }
        }
    );
}

value!(i8, 1);
value!(u8, 1);
value!(i16, 2);
value!(u16, 2);
value!(u32, 4);
value!(i64, 8);
value!([u8; 3], 1);
value!([i8; 4], 1);
value!([u8; 4], 1);
value!([u8; 10], 1);

impl<V> Walue<'static> for Vec<V>
where
    V: Value,
{
    type Parameter = usize;

    fn read<T: Tape>(tape: &mut T, count: usize) -> Result<Self> {
        let mut values = Vec::with_capacity(count);
        for _ in 0..count {
            values.push(Value::read(tape)?);
        }
        Ok(values)
    }
}