zenith_foundation/
varint.rs1pub const MAX_VARINT_SIZE: usize = 8;
17
18pub const MAX_VARINT_VALUE: u64 = (1u64 << 62) - 1;
20
21#[inline]
26pub fn encode_varint_buf(value: u64, out: &mut [u8]) -> Result<usize, &'static str> {
27 if out.len() < MAX_VARINT_SIZE {
28 return Err("buffer too small for varint encoding");
29 }
30 if value < 64 {
31 out[0] = value as u8;
32 Ok(1)
33 } else if value < 16384 {
34 out[0] = 0x40 | ((value >> 8) as u8);
35 out[1] = (value & 0xFF) as u8;
36 Ok(2)
37 } else if value < (1u64 << 30) {
38 out[0] = 0x80 | ((value >> 24) as u8);
39 out[1] = ((value >> 16) & 0xFF) as u8;
40 out[2] = ((value >> 8) & 0xFF) as u8;
41 out[3] = (value & 0xFF) as u8;
42 Ok(4)
43 } else if value <= MAX_VARINT_VALUE {
44 out[0] = 0xC0 | (((value >> 56) & 0x3F) as u8);
46 out[1] = ((value >> 48) & 0xFF) as u8;
47 out[2] = ((value >> 40) & 0xFF) as u8;
48 out[3] = ((value >> 32) & 0xFF) as u8;
49 out[4] = ((value >> 24) & 0xFF) as u8;
50 out[5] = ((value >> 16) & 0xFF) as u8;
51 out[6] = ((value >> 8) & 0xFF) as u8;
52 out[7] = (value & 0xFF) as u8;
53 Ok(8)
54 } else {
55 Err("varint value exceeds maximum (2^62 - 1)")
57 }
58}
59
60#[inline]
66pub fn encode_varint(value: u64, out: &mut Vec<u8>) -> Result<(), &'static str> {
67 let mut buf = [0u8; MAX_VARINT_SIZE];
68 let len = encode_varint_buf(value, &mut buf)?;
69 out.extend_from_slice(&buf[..len]);
70 Ok(())
71}
72
73#[inline]
79pub fn parse_varint(input: &[u8]) -> Option<(u64, usize)> {
80 if input.is_empty() {
81 return None;
82 }
83 let first = input[0];
84 let len_tag = first >> 6;
85 let len = 1usize << len_tag;
86 if input.len() < len {
87 return None;
88 }
89 let mut v: u64 = (first & 0x3F) as u64;
90 for &b in input.iter().take(len).skip(1) {
91 v = (v << 8) | (b as u64);
92 }
93 Some((v, len))
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
102 fn test_rfc9000_appendix_a_known_values() {
103 let cases: &[(u64, &[u8])] = &[
105 (37, &[0x25]),
106 (63, &[0x3f]),
107 (64, &[0x40, 0x40]),
108 (83, &[0x40, 0x53]),
109 (15_293, &[0x7b, 0xbd]),
110 (16_383, &[0x7f, 0xff]),
111 (16_384, &[0x80, 0x00, 0x40, 0x00]),
112 (494_878_333, &[0x9d, 0x7f, 0x3e, 0x7d]),
113 (1_073_741_823, &[0xbf, 0xff, 0xff, 0xff]),
114 (1_073_741_824, &[0xc0, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]),
115 (151_288_809_941_952_652, &[0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c]),
117 ((1u64 << 62) - 1, &[0xff; 8]),
118 ];
119 for (value, expected) in cases {
120 let mut buf = [0u8; MAX_VARINT_SIZE];
121 let n = encode_varint_buf(*value, &mut buf).unwrap();
122 assert_eq!(&buf[..n], *expected, "encode({value}) mismatch");
123 let mut v = Vec::new();
124 encode_varint(*value, &mut v).unwrap();
125 assert_eq!(v.as_slice(), *expected, "encode_vec({value}) mismatch");
126 }
127 }
128
129 #[test]
130 fn test_over_max_rejected() {
131 let mut buf = [0u8; MAX_VARINT_SIZE];
132 assert!(encode_varint_buf(1u64 << 62, &mut buf).is_err());
133 let mut v = Vec::new();
134 assert!(encode_varint(u64::MAX, &mut v).is_err());
135 assert!(v.is_empty(), "fail-closed: 拒绝时不得写入任何字节");
136 }
137
138 #[test]
139 fn test_small_buffer_rejected() {
140 let mut buf = [0u8; 4];
141 assert!(encode_varint_buf(37, &mut buf).is_err());
142 }
143}