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
use std::io::Cursor;

use anyhow::{anyhow, Result};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

/// The `Marshal` trait is used for marshaling and unmarshaling MKVS trees.
pub trait Marshal {
    /// Marshal the object into a binary form and return it as a new vector.
    fn marshal_binary(&self) -> Result<Vec<u8>>;
    /// Unmarshal from the given byte slice reference and modify `self`.
    fn unmarshal_binary(&mut self, data: &[u8]) -> Result<usize>;
}

impl Marshal for u16 {
    fn marshal_binary(&self) -> Result<Vec<u8>> {
        let mut result: Vec<u8> = Vec::with_capacity(2);
        result.write_u16::<LittleEndian>(*self)?;
        Ok(result)
    }

    fn unmarshal_binary(&mut self, data: &[u8]) -> Result<usize> {
        if data.len() < 2 {
            Err(anyhow!("mkvs: malformed 16-bit integer"))
        } else {
            let mut reader = Cursor::new(data);
            *self = reader.read_u16::<LittleEndian>()?;
            Ok(2)
        }
    }
}

impl Marshal for u32 {
    fn marshal_binary(&self) -> Result<Vec<u8>> {
        let mut result: Vec<u8> = Vec::with_capacity(4);
        result.write_u32::<LittleEndian>(*self)?;
        Ok(result)
    }

    fn unmarshal_binary(&mut self, data: &[u8]) -> Result<usize> {
        if data.len() < 4 {
            Err(anyhow!("mkvs: malformed 32-bit integer"))
        } else {
            let mut reader = Cursor::new(data);
            *self = reader.read_u32::<LittleEndian>()?;
            Ok(4)
        }
    }
}

impl Marshal for u64 {
    fn marshal_binary(&self) -> Result<Vec<u8>> {
        let mut result: Vec<u8> = Vec::with_capacity(8);
        result.write_u64::<LittleEndian>(*self)?;
        Ok(result)
    }

    fn unmarshal_binary(&mut self, data: &[u8]) -> Result<usize> {
        if data.len() < 8 {
            Err(anyhow!("mkvs: malformed 64-bit integer"))
        } else {
            let mut reader = Cursor::new(data);
            *self = reader.read_u64::<LittleEndian>()?;
            Ok(8)
        }
    }
}