1const INDEXED: u8 = 0b1000_0000;
30const INDEXED_WITH_POST_BASE: u8 = 0b0001_0000;
31const LITERAL: u8 = 0b0010_0000;
32const LITERAL_WITH_NAME_REF: u8 = 0b0100_0000;
33
34pub type Result<T> = std::result::Result<T, Error>;
41
42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub enum Error {
45 BufferTooShort,
47
48 InflatedHuffmanEncoding,
50
51 InvalidHuffmanEncoding,
53
54 InvalidStaticTableIndex,
56
57 InvalidHeaderValue,
59
60 HeaderListTooLarge,
62}
63
64impl std::fmt::Display for Error {
65 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
66 write!(f, "{self:?}")
67 }
68}
69
70impl std::error::Error for Error {
71 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
72 None
73 }
74}
75
76impl std::convert::From<octets::BufferTooShortError> for Error {
77 fn from(_err: octets::BufferTooShortError) -> Self {
78 Error::BufferTooShort
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use crate::*;
85
86 use super::*;
87
88 #[test]
89 fn encode_decode() {
90 let mut encoded = [0u8; 240];
91
92 let headers = vec![
93 h3::Header::new(b":path", b"/rsrc.php/v3/yn/r/rIPZ9Qkrdd9.png"),
94 h3::Header::new(b"accept-encoding", b"gzip, deflate, br"),
95 h3::Header::new(b"accept-language", b"en-US,en;q=0.9"),
96 h3::Header::new(b"user-agent", b"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.70 Safari/537.36"),
97 h3::Header::new(b"accept", b"image/webp,image/apng,image/*,*/*;q=0.8"),
98 h3::Header::new(b"referer", b"https://static.xx.fbcdn.net/rsrc.php/v3/yT/l/0,cross/dzXGESIlGQQ.css"),
99 h3::Header::new(b":authority", b"static.xx.fbcdn.net"),
100 h3::Header::new(b":scheme", b"https"),
101 h3::Header::new(b":method", b"GET"),
102 ];
103
104 let mut enc = Encoder::new();
105 assert_eq!(enc.encode(&headers, &mut encoded), Ok(240));
106
107 let mut dec = Decoder::new();
108 assert_eq!(dec.decode(&encoded, u64::MAX), Ok(headers));
109 }
110
111 #[test]
112 fn lower_case() {
113 let mut encoded = [0u8; 35];
114
115 let headers_expected = vec![
116 crate::h3::Header::new(b":status", b"200"),
117 crate::h3::Header::new(b":path", b"/HeLlO"),
118 crate::h3::Header::new(b"woot", b"woot"),
119 crate::h3::Header::new(b"hello", b"WorlD"),
120 crate::h3::Header::new(b"foo", b"BaR"),
121 ];
122
123 let headers_in = vec![
125 crate::h3::Header::new(b":StAtUs", b"200"),
126 crate::h3::Header::new(b":PaTh", b"/HeLlO"),
127 crate::h3::Header::new(b"WooT", b"woot"),
128 crate::h3::Header::new(b"hello", b"WorlD"),
129 crate::h3::Header::new(b"fOo", b"BaR"),
130 ];
131
132 let mut enc = Encoder::new();
133 assert_eq!(enc.encode(&headers_in, &mut encoded), Ok(35));
134
135 let mut dec = Decoder::new();
136 let headers_out = dec.decode(&encoded, u64::MAX).unwrap();
137
138 assert_eq!(headers_expected, headers_out);
139
140 let headers_in = vec![
142 crate::h3::HeaderRef::new(b":StAtUs", b"200"),
143 crate::h3::HeaderRef::new(b":PaTh", b"/HeLlO"),
144 crate::h3::HeaderRef::new(b"WooT", b"woot"),
145 crate::h3::HeaderRef::new(b"hello", b"WorlD"),
146 crate::h3::HeaderRef::new(b"fOo", b"BaR"),
147 ];
148
149 let mut enc = Encoder::new();
150 assert_eq!(enc.encode(&headers_in, &mut encoded), Ok(35));
151
152 let mut dec = Decoder::new();
153 let headers_out = dec.decode(&encoded, u64::MAX).unwrap();
154
155 assert_eq!(headers_expected, headers_out);
156 }
157
158 #[test]
159 fn lower_ascii_range() {
160 let mut encoded = [0u8; 50];
161 let mut enc = Encoder::new();
162
163 let headers1 =
165 vec![crate::h3::Header::new(b"location", b" ")];
166 assert_eq!(enc.encode(&headers1, &mut encoded), Ok(19));
167
168 let headers2 = vec![crate::h3::Header::new(b"a", b"")];
170 assert_eq!(enc.encode(&headers2, &mut encoded), Ok(20));
171
172 let headers3 = vec![crate::h3::Header::new(b" ", b"hello")];
173 assert_eq!(enc.encode(&headers3, &mut encoded), Ok(24));
174 }
175
176 #[test]
177 fn extended_ascii_range() {
178 let mut encoded = [0u8; 50];
179 let mut enc = Encoder::new();
180
181 let name = b"location";
182 let value = "£££££££££££££££";
183
184 let headers1 = vec![crate::h3::Header::new(name, value.as_bytes())];
186 assert_eq!(enc.encode(&headers1, &mut encoded), Ok(34));
187
188 let value = "ððððððððððððððð";
190 let headers2 = vec![crate::h3::Header::new(b"a", value.as_bytes())];
191 assert_eq!(enc.encode(&headers2, &mut encoded), Ok(35));
192
193 let headers3 = vec![crate::h3::Header::new(value.as_bytes(), b"hello")];
194 assert_eq!(enc.encode(&headers3, &mut encoded), Ok(39));
195 }
196}
197
198pub use decoder::Decoder;
199pub use encoder::Encoder;
200
201mod decoder;
202mod encoder;
203mod huffman;
204mod static_table;