summaryrefslogtreecommitdiff
path: root/matrix-lang/src/binary/prim.rs
blob: 44e68986f3054a90369d894cbd5f8f299609ca15 (plain)
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
use super::Primitive;
use std::io::{self, Read, Write};

macro_rules! marshal_number {
    ($type:ident, $byte:expr) => {
        impl Primitive for $type {
            fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
                write.write(&self.to_le_bytes())?;
                Ok(())
            }

            fn read<R: Read>(read: &mut R) -> io::Result<Self> {
                let mut bytes = [0u8; $byte];
                read.read_exact(&mut bytes)?;
                Ok(Self::from_le_bytes(bytes))
            }
        }
    };
}

marshal_number!(u8, 1);
marshal_number!(u16, 2);
marshal_number!(i16, 2);
marshal_number!(u32, 4);
marshal_number!(i64, 8);
marshal_number!(f64, 8);

impl Primitive for bool {
    fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
        if *self {
            write.write(&[1u8; 1])?;
        } else {
            write.write(&[0u8; 1])?;
        }
        Ok(())
    }

    fn read<R: Read>(read: &mut R) -> io::Result<Self> {
        let mut bytes = [0u8; 1];
        read.read_exact(&mut bytes)?;
        if bytes[0] == 1 {
            Ok(true)
        } else {
            Ok(false)
        }
    }
}

impl Primitive for String {
    fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
        let bytes = self.as_bytes();
        let len = bytes.len();
        write.write(&(len as u32).to_le_bytes())?;
        write.write(&bytes)?;
        Ok(())
    }

    fn read<R: Read>(read: &mut R) -> io::Result<Self> {
        let len = usize::read(read)?;
        let mut bytes = vec![0u8; len];
        read.read_exact(&mut bytes)?;
        Ok(String::from_utf8_lossy(bytes.as_slice()).to_string())
    }
}

impl Primitive for usize {
    fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
        (*self as u32).write(write)
    }

    fn read<R: Read>(read: &mut R) -> io::Result<Self> {
        Ok(u32::read(read)? as usize)
    }
}

pub struct VarInt(pub usize);

impl Primitive for VarInt {
    fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
        let mut data = self.0;
        loop {
            let mut byte = (data & 0x7F) as u8;
            data >>= 7;
            if data != 0 {
                byte += 0x80;
            }
            write.write(&[byte; 1])?;
            if data == 0 {
                return Ok(())
            }
        }
    }

    fn read<R: Read>(read: &mut R) -> io::Result<Self> {
        let mut buf = [0];
        let mut result = 0usize;
        for count in 0..8 {
            if read.read(&mut buf)? != 1 {
                return Ok(Self(0))
            }
            let byte = buf[0];
            result |= ((byte &  0x7F) as usize) << (7 * count);
            if byte & 0x80 == 0 {
                return Ok(Self(result))
            }
        }
        Ok(Self(0))
    }
}