serde_jam/compact/
vlen.rs1use crate::{Vec, compact::Numeric, vec};
4
5pub const THRESHOLDS: [(usize, u8, u8, u64, u64); 7] = [
7 (1, 0x80, 0xc0, 0x100, 0x4000),
9 (2, 0xc0, 0xe0, 0x10000, 0x200000),
11 (3, 0xe0, 0xf0, 0x1000000, 0x10000000),
13 (4, 0xf0, 0xf8, 0x100000000, 0x800000000),
15 (5, 0xf8, 0xfc, 0x10000000000, 0x40000000000),
17 (6, 0xfc, 0xfe, 0x1000000000000, 0x2000000000000),
19 (7, 0xfe, 0xff, 0x100000000000000, 0x100000000000000),
21];
22
23pub fn encode(value: u64) -> Vec<u8> {
25 if value < 0x80 {
26 return vec![value as u8];
27 }
28
29 for (length, base, _, bits, threshold) in THRESHOLDS.into_iter() {
31 if value < threshold {
32 let mut encoded = vec![base + (value / bits) as u8];
33 let remainder = (value % bits).encode();
34 encoded.extend_from_slice(&remainder);
36 while encoded.len() < length + 1 {
37 encoded.push(0);
38 }
39
40 return encoded;
41 }
42 }
43
44 [vec![255], value.to_le_bytes().to_vec()].concat()
45}
46
47pub fn decode(encoded: &[u8]) -> u64 {
49 self::decode_from(encoded).0
50}
51
52pub fn decode_from(encoded: &[u8]) -> (u64, usize) {
54 if encoded.is_empty() {
55 return (0, 0);
56 }
57
58 let prefix = encoded[0];
59 if prefix < 0x80 {
60 return (prefix as u64, 1);
61 }
62
63 for (length, base, next, bits, _) in THRESHOLDS.into_iter() {
65 if prefix < next {
66 let dlen = length + 1;
67 return (
68 ((prefix - base) as u64) * bits + u64::decode(&encoded[1..dlen]),
69 dlen,
70 );
71 }
72 }
73
74 (u64::decode(&encoded[1..9]), 9)
75}
76
77#[test]
78fn thresholds() {
79 for (length, base, _, bits, threshold) in THRESHOLDS.into_iter() {
80 assert_eq!(bits.trailing_zeros(), 8 * length as u32);
81
82 let expected = 2u64.pow(8_u32) - 2u64.pow((8 - length) as u32);
84 assert_eq!(base, expected as u8);
85
86 let expected = 2u64.pow(7 * (length + 1) as u32);
88 assert_eq!(threshold, expected,);
89 }
90}
91
92#[test]
93fn roundtrip() {
94 for (length, _, _, _, threshold) in THRESHOLDS.iter() {
95 let value = threshold - 1;
96 let encoded = encode(value);
97 let (decoded, dlen) = decode_from(&encoded);
98 assert_eq!(dlen, *length + 1);
99 assert_eq!(encoded.len(), dlen);
100 assert_eq!(value, decoded);
101 }
102}
103
104#[test]
105fn vlen_zero() {
106 assert_eq!(encode(0), vec![0]);
107}