Skip to main content

zenith_foundation/
varint.rs

1//! QUIC 变长整数编码(RFC 9000 §16 唯一实现)
2//!
3//! 全 workspace 唯一实现:zenith-http3(帧层)、zenith-net(QUIC 头构造)
4//! 统一经 zenith-http3 re-export 本模块,禁止重复实现。
5//!
6//! # 编码格式
7//! - 1 字节: 00xxxxxx (0-63)
8//! - 2 字节: 01xxxxxx xxxxxxxx (64-16383)
9//! - 4 字节: 10xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx (16384-2^30-1)
10//! - 8 字节: 11xxxxxx xxxxxxxx ... (2^30-2^62-1)
11//!
12//! # 边界保证
13//! 当 value >= 2^62 时严格返回错误(fail-closed,禁止静默截断高位)。
14
15/// RFC 9000 varint 最大编码长度(字节)
16pub const MAX_VARINT_SIZE: usize = 8;
17
18/// RFC 9000 varint 最大可编码值(2^62 - 1)
19pub const MAX_VARINT_VALUE: u64 = (1u64 << 62) - 1;
20
21/// 编码 QUIC 变长度整数到固定输出缓冲区(fail-closed)
22///
23/// # 返回
24/// 写入的字节数,或缓冲区不足/值超界时返回错误。
25#[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        // 8 字节: 2 位长度标签 (11) + 6 位最高有效位
45        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        // 值 >= 2^62 超过 RFC 9000 上限,严格 fail-closed
56        Err("varint value exceeds maximum (2^62 - 1)")
57    }
58}
59
60/// 编码 QUIC 变长度整数到 Vec(fail-closed 包装器)
61///
62/// # 错误
63/// 值 >= 2^62(超出 RFC 9000 varint 上限)时返回错误,严格 fail-closed,
64/// 禁止静默丢弃编码失败。
65#[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/// 解析 QUIC/HTTP/3 变长度整数 (RFC 9000 §16)
74///
75/// 返回 `(value, consumed_bytes)`;输入为空或不足时返回 `None`(fail-closed)。
76/// 与 [`encode_varint_buf`] / [`encode_varint`] 共同覆盖 RFC 9000 §16 编解码,
77/// 为全 workspace varint 解码的唯一实现(HTTP/3 帧层、QUIC 帧解析统一复用)。
78#[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    /// RFC 9000 §A.1 Sample Variable-Length Integer Decoding 已知值(编码方向)
101    #[test]
102    fn test_rfc9000_appendix_a_known_values() {
103        // (value, expected minimal-length encoding)
104        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            // RFC 9000 §A.1 样例字节:0xc2197c5eff14e88c → 151,288,809,941,952,652
116            (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}