cellos_supervisor/sni_proxy/h2/hpack/
integer.rs1use super::super::error::H2ParseError;
8
9pub fn decode_integer(buf: &[u8], prefix_bits: u32) -> Result<(u64, &[u8]), H2ParseError> {
13 if buf.is_empty() {
14 return Err(H2ParseError::MalformedHeaders);
15 }
16 let mask: u8 = ((1u16 << prefix_bits) - 1) as u8;
17 let prefix = buf[0] & mask;
18 if prefix < mask {
19 return Ok((prefix as u64, &buf[1..]));
20 }
21 let mut value: u64 = mask as u64;
24 let mut shift: u32 = 0;
25 let mut idx: usize = 1;
26 loop {
27 if idx >= buf.len() {
28 return Err(H2ParseError::MalformedHeaders);
29 }
30 let b = buf[idx];
31 idx += 1;
32 let chunk = (b & 0x7F) as u64;
33 let shifted = chunk
34 .checked_shl(shift)
35 .ok_or(H2ParseError::MalformedHeaders)?;
36 value = value
37 .checked_add(shifted)
38 .ok_or(H2ParseError::MalformedHeaders)?;
39 if b & 0x80 == 0 {
40 return Ok((value, &buf[idx..]));
41 }
42 shift = shift.checked_add(7).ok_or(H2ParseError::MalformedHeaders)?;
43 if shift >= 64 {
44 return Err(H2ParseError::MalformedHeaders);
45 }
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn decodes_short_form_under_prefix_max() {
55 let (v, rest) = decode_integer(&[0x0A, 0xAA], 7).unwrap();
57 assert_eq!(v, 10);
58 assert_eq!(rest, &[0xAA]);
59 }
60
61 #[test]
62 fn decodes_multi_octet_form() {
63 let (v, _) = decode_integer(&[0x7F, 0x05], 7).unwrap();
65 assert_eq!(v, 127 + 5);
66 }
67
68 #[test]
69 fn rejects_unbounded_continuation() {
70 let buf: Vec<u8> = std::iter::once(0x7F)
72 .chain(std::iter::repeat_n(0xFF, 16))
73 .collect();
74 assert!(decode_integer(&buf, 7).is_err());
75 }
76}