concordium_base/common/
version.rs1use super::*;
2use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
3
4pub const VERSION_0: Version = Version { value: 0 };
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, SerdeSerialize, SerdeDeserialize)]
12#[serde(transparent)]
13pub struct Version {
14 pub value: u32,
15}
16
17impl From<u32> for Version {
18 fn from(value: u32) -> Version {
19 Version { value }
20 }
21}
22
23impl From<Version> for u32 {
24 fn from(val: Version) -> u32 {
25 val.value
26 }
27}
28
29impl std::fmt::Display for Version {
30 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
31 write!(f, "{}", self.value)
32 }
33}
34
35impl Serial for Version {
36 fn serial<B: Buffer>(&self, out: &mut B) {
37 if self.value == 0 {
38 out.write_u8(0).expect("Writing to buffer is safe");
39 return;
40 }
41
42 let mut buf: [u8; 5] = [0; 5];
44 let mut v = self.value;
45 let mut len = 0;
46 while v > 0 {
47 buf[len] = (1 << 7) | (v & 0b0111_1111) as u8;
48 v >>= 7;
49 len += 1;
50 }
51
52 let buf = &mut buf[..len];
54 buf[0] &= 0b0111_1111;
55 buf.reverse();
56 out.write_all(buf).expect("Writing to buffer is safe");
57 }
58}
59
60impl Deserial for Version {
61 fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
62 let mut acc: u64 = 0;
63 for _ in 0..5 {
64 let byte = u64::from(source.read_u8()?);
65 if byte >= 0b1000_0000 {
66 acc = (acc << 7) | (byte & 0b0111_1111);
67 } else {
68 acc = (acc << 7) | byte;
69 break;
70 }
71 }
72 let value: u32 = acc.try_into()?;
73 Ok(Version::from(value))
74 }
75}
76
77#[derive(Clone, Copy, Debug, Eq, PartialEq, SerdeSerialize, SerdeDeserialize)]
83pub struct Versioned<T> {
84 #[serde(rename = "v")]
85 pub version: Version,
86 #[serde(rename = "value")]
87 pub value: T,
88}
89
90impl<T> Versioned<T> {
91 pub fn new(version: Version, value: T) -> Versioned<T> {
92 Versioned { version, value }
93 }
94}
95
96impl<T: Serial> Serial for Versioned<T> {
97 fn serial<B: Buffer>(&self, out: &mut B) {
98 out.put(&self.version);
99 out.put(&self.value);
100 }
101}
102
103impl<T: Deserial> Deserial for Versioned<T> {
104 fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
105 let version: Version = source.get()?;
106 let value: T = source.get()?;
107 Ok(Versioned { version, value })
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use rand::{thread_rng, RngCore};
115
116 #[test]
117 fn test_version_serialization_testvector() {
118 let test = Version::from(1_700_794_014);
119 let actual: Vec<u8> = vec![0x86, 0xab, 0x80, 0x9d, 0x1e];
120 let mut buffer: Vec<u8> = Vec::new();
121 test.serial(&mut buffer);
122 assert_eq!(buffer, actual);
123 }
124
125 #[test]
126 fn test_version_serialization_minmax() {
127 let min = Version::from(0);
128 let max = Version::from(u32::MAX);
129 let min_actual: Vec<u8> = vec![0x00];
130 let max_actual: Vec<u8> = vec![0x8F, 0xFF, 0xFF, 0xFF, 0x7F];
131 let mut buffer: Vec<u8> = Vec::new();
132 min.serial(&mut buffer);
133 assert_eq!(buffer, min_actual);
134 let mut buffer: Vec<u8> = Vec::new();
135 max.serial(&mut buffer);
136 assert_eq!(buffer, max_actual);
137 }
138
139 #[test]
140 fn test_version_serialization_overflow() {
141 let data: Vec<u8> = vec![0x9F, 0xFF, 0xFF, 0xFF, 0x7F];
142 let mut cursor = std::io::Cursor::new(data);
143 let version: ParseResult<Version> = cursor.get();
144 assert!(version.is_err());
145 }
146
147 #[test]
148 fn test_version_serialization_random() {
149 let mut rng = thread_rng();
150 for _ in 0..1000 {
151 let actual = Version::from(rng.next_u32());
152 let parsed = serialize_deserialize(&actual)
153 .expect("Deserialization of a serialized value failed");
154 assert_eq!(actual, parsed);
155 }
156 }
157}