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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use super::*;
use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};

/// Version 0 as a constant for ease of use.
pub const VERSION_0: Version = Version { value: 0 };

/// Version of the serialization of a data structure. Binary coded as a variable
/// integer represented by bytes, where MSB=1 indicates more bytes follow, and
/// the 7 lower bits in a byte is Big Endian data bits for the value. A version
/// number is bounded by u32 max.
#[derive(Debug, Clone, Copy, PartialEq, Eq, SerdeSerialize, SerdeDeserialize)]
#[serde(transparent)]
pub struct Version {
    pub value: u32,
}

impl From<u32> for Version {
    fn from(value: u32) -> Version { Version { value } }
}

impl From<Version> for u32 {
    fn from(val: Version) -> u32 { val.value }
}

impl std::fmt::Display for Version {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.value) }
}

impl Serial for Version {
    fn serial<B: Buffer>(&self, out: &mut B) {
        if self.value == 0 {
            out.write_u8(0).expect("Writing to buffer is safe");
            return;
        }

        // Create 7-bit encoding with all MSB set to 1
        let mut buf: [u8; 5] = [0; 5];
        let mut v = self.value;
        let mut len = 0;
        while v > 0 {
            buf[len] = (1 << 7) | (v & 0b0111_1111) as u8;
            v >>= 7;
            len += 1;
        }

        // Convert to BigEndian, ensure last byte has MSB=0, write to buffer
        let buf = &mut buf[..len];
        buf[0] &= 0b0111_1111;
        buf.reverse();
        out.write_all(buf).expect("Writing to buffer is safe");
    }
}

impl Deserial for Version {
    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
        let mut acc: u64 = 0;
        for _ in 0..5 {
            let byte = u64::from(source.read_u8()?);
            if byte >= 0b1000_0000 {
                acc = (acc << 7) | (byte & 0b0111_1111);
            } else {
                acc = (acc << 7) | byte;
                break;
            }
        }
        let value: u32 = acc.try_into()?;
        Ok(Version::from(value))
    }
}

/// [`Versioned<T>`](Versioned) represents `T` as a versioned data-structure.
/// The version is a integer number up to the implementation,
/// which is serialized using variable integer encoding.
/// The caller is responsible for ensuring the data structure `T`
/// is compatible with the version number.
#[derive(Clone, Copy, Debug, Eq, PartialEq, SerdeSerialize, SerdeDeserialize)]
pub struct Versioned<T> {
    #[serde(rename = "v")]
    pub version: Version,
    #[serde(rename = "value")]
    pub value:   T,
}

impl<T> Versioned<T> {
    pub fn new(version: Version, value: T) -> Versioned<T> { Versioned { version, value } }
}

impl<T: Serial> Serial for Versioned<T> {
    fn serial<B: Buffer>(&self, out: &mut B) {
        out.put(&self.version);
        out.put(&self.value);
    }
}

impl<T: Deserial> Deserial for Versioned<T> {
    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
        let version: Version = source.get()?;
        let value: T = source.get()?;
        Ok(Versioned { version, value })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use rand::{thread_rng, RngCore};

    #[test]
    fn test_version_serialization_testvector() {
        let test = Version::from(1_700_794_014);
        let actual: Vec<u8> = vec![0x86, 0xab, 0x80, 0x9d, 0x1e];
        let mut buffer: Vec<u8> = Vec::new();
        test.serial(&mut buffer);
        assert_eq!(buffer, actual);
    }

    #[test]
    fn test_version_serialization_minmax() {
        let min = Version::from(0);
        let max = Version::from(u32::max_value());
        let min_actual: Vec<u8> = vec![0x00];
        let max_actual: Vec<u8> = vec![0x8F, 0xFF, 0xFF, 0xFF, 0x7F];
        let mut buffer: Vec<u8> = Vec::new();
        min.serial(&mut buffer);
        assert_eq!(buffer, min_actual);
        let mut buffer: Vec<u8> = Vec::new();
        max.serial(&mut buffer);
        assert_eq!(buffer, max_actual);
    }

    #[test]
    fn test_version_serialization_overflow() {
        let data: Vec<u8> = vec![0x9F, 0xFF, 0xFF, 0xFF, 0x7F];
        let mut cursor = std::io::Cursor::new(data);
        let version: ParseResult<Version> = cursor.get();
        assert!(version.is_err());
    }

    #[test]
    fn test_version_serialization_random() {
        let mut rng = thread_rng();
        for _ in 0..1000 {
            let actual = Version::from(rng.next_u32());
            let parsed = serialize_deserialize(&actual)
                .expect("Deserialization of a serialized value failed");
            assert_eq!(actual, parsed);
        }
    }
}