binary_codec/
dyn_int.rs

1use crate::{DeserializationError, SerializationError, SerializerConfig};
2
3/// Gives encoded size in bytes
4///
5/// # Arguments
6/// * `nr` - number to encode
7pub fn encoded_size(nr: u128) -> usize {
8    let mut res = 0;
9    let mut nr = nr;
10    while nr > 0 {
11        nr /= 128;
12        res += 1;
13    }
14    res
15}
16
17/// Encodes a number into a vector of bytes.
18///
19/// # Arguments
20/// * `nr` - number to encode
21pub fn encode(nr: u128) -> Vec<u8> {
22    let mut res = Vec::new();
23    let mut nr = nr;
24    while nr > 0 {
25        let mut encoded = nr % 128;
26        nr /= 128;
27        if nr > 0 {
28            encoded |= 128;
29        }
30        res.push(encoded as u8);
31    }
32    res
33}
34
35/// Decodes a number from a slice of bytes.
36///
37/// # Arguments
38/// * `data` - slice of bytes to decode
39pub fn decode(data: &[u8]) -> u128 {
40    let mut num = 0;
41    let mut multiplier = 1;
42    for byte in data {
43        num += (*byte as u128 & 127) * multiplier;
44        multiplier *= 128;
45    }
46    num
47}
48
49/// Decodes a number from a slice of bytes when size of encoded number is unknown, returning the number and the number of bytes read.
50///
51/// # Arguments
52/// * `data` - slice of bytes to decode number from
53///
54/// # Returns
55/// * (number, bytes read)
56pub fn read_from_slice(data: &[u8]) -> Result<(u128, usize), DeserializationError> {
57    let mut idx = 0;
58    loop {
59        if idx > data.len() - 1 {
60            break Err(DeserializationError::NotEnoughBytes(1));
61        }
62
63        if (data[idx] & 1 << 7) == 0 {
64            break Ok((decode(&data[..=idx]), idx + 1));
65        }
66
67        idx += 1;
68    }
69}
70
71pub fn read_dynint<T : Clone>(
72    bytes: &[u8],
73    config: &mut SerializerConfig<T>
74) -> Result<u128, DeserializationError> {
75    config.reset_bits(true);
76    let (value, read_bytes) = read_from_slice(&bytes[config.pos..])?;
77    config.pos += read_bytes;
78    Ok(value)
79}
80
81pub fn write_dynint<T : Clone>(
82    val: u128,
83    bytes: &mut Vec<u8>,
84    config: &mut SerializerConfig<T>
85) -> Result<(), SerializationError> {
86    config.reset_bits(false);
87    let data = encode(val);
88    bytes.extend_from_slice(&data);
89    config.pos += data.len();
90    Ok(())
91}
92
93
94#[cfg(test)]
95mod test {
96    use super::*;
97
98    #[test]
99    fn can_encode_decode_number() {
100        let number = 1234567890;
101        let encoded = encode(number);
102        let decoded = decode(&encoded);
103        assert_eq!(number, decoded);
104        assert_eq!(5, encoded.len()); // 1234567890 ~ 2^31, 7 bits per byte = 7 * 5 = 35
105    }
106
107    #[test]
108    fn can_decode_number() {
109        let nr = &[216u8, 4];
110        let res = decode(nr);
111        assert_eq!(600, res);
112    }
113
114    #[test]
115    fn can_decode_number_from_larger_slice() {
116        let nr = &[216u8, 4, 234, 19, 74];
117        let res = read_from_slice(nr).unwrap();
118        assert_eq!((600, 2), res);
119    }
120
121    #[test]
122    fn can_decode_number_in_4_bytes() {
123        let max_nr = 268435455; // max number in 4 bytes
124        let encoded = encode(max_nr);
125        assert_eq!(4, encoded.len());
126    }
127
128    #[test]
129    fn cant_decode_bignr_in_4_bytes() {
130        let max_nr = 268435456;
131        let encoded = encode(max_nr);
132        assert_ne!(4, encoded.len());
133    }
134
135    #[test]
136    fn cant_decode_slice_that_lies() {
137        let slice = &[0b10111110]; // slice notes there is a second byte (7th bit, right-to-left), but there's not
138        let decoded = read_from_slice(slice);
139        assert!(decoded.is_err());
140    }
141
142    #[test]
143    fn can_encode_nr_lt_128_in_1_byte() {
144        let encoded = encode(127);
145        assert_eq!(1, encoded.len());
146    }
147
148    #[test]
149    fn can_guess_encoded_size() {
150        let one_byte = 127;
151        assert_eq!(1, encoded_size(one_byte));
152
153        let two_bytes = 128;
154        assert_eq!(2, encoded_size(two_bytes));
155
156        let four_bytes = 268435455;
157        assert_eq!(4, encoded_size(four_bytes));
158    }
159}