1use crate::varint::{Moqt17, Moqt18, VarInt, VarIntError};
4use bytes::{Buf, BufMut};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum VarIntEncoding {
13 Rfc9000,
16 Moqt17,
20 Moqt18,
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
27pub enum DraftVersion {
28 Draft07,
30 Draft08,
32 Draft09,
34 Draft10,
36 Draft11,
38 Draft12,
40 Draft13,
42 Draft14,
44 Draft15,
46 Draft16,
48 Draft17,
50 Draft18,
52 Draft19,
54 Draft20,
56}
57
58impl DraftVersion {
59 pub fn version_varint(&self) -> VarInt {
76 let n = match self {
77 DraftVersion::Draft07 => 7,
78 DraftVersion::Draft08 => 8,
79 DraftVersion::Draft09 => 9,
80 DraftVersion::Draft10 => 10,
81 DraftVersion::Draft11 => 11,
82 DraftVersion::Draft12 => 12,
83 DraftVersion::Draft13 => 13,
84 DraftVersion::Draft14 => 14,
85 DraftVersion::Draft15 => 15,
86 DraftVersion::Draft16 => 16,
87 DraftVersion::Draft17 => 17,
88 DraftVersion::Draft18 => 18,
89 DraftVersion::Draft19 => 19,
90 DraftVersion::Draft20 => 20,
91 };
92 VarInt::from_usize(0xff000000 + n as usize)
93 }
94
95 pub fn quic_alpn(&self) -> &'static [u8] {
102 match self {
103 DraftVersion::Draft07
104 | DraftVersion::Draft08
105 | DraftVersion::Draft09
106 | DraftVersion::Draft10
107 | DraftVersion::Draft11
108 | DraftVersion::Draft12
109 | DraftVersion::Draft13
110 | DraftVersion::Draft14 => b"moq-00",
111 DraftVersion::Draft15 => b"moqt-15",
112 DraftVersion::Draft16 => b"moqt-16",
113 DraftVersion::Draft17 => b"moqt-17",
114 DraftVersion::Draft18 => b"moqt-18",
115 DraftVersion::Draft19 => b"moqt-19",
116 DraftVersion::Draft20 => b"moqt-20",
117 }
118 }
119
120 pub fn from_alpn(alpn: &[u8]) -> Option<DraftVersion> {
128 match alpn {
129 b"moqt-15" => Some(DraftVersion::Draft15),
130 b"moqt-16" => Some(DraftVersion::Draft16),
131 b"moqt-17" => Some(DraftVersion::Draft17),
132 b"moqt-18" => Some(DraftVersion::Draft18),
133 b"moqt-19" => Some(DraftVersion::Draft19),
134 b"moqt-20" => Some(DraftVersion::Draft20),
135 _ => None,
136 }
137 }
138
139 pub fn from_number(n: u8) -> Option<DraftVersion> {
143 match n {
144 7 => Some(DraftVersion::Draft07),
145 8 => Some(DraftVersion::Draft08),
146 9 => Some(DraftVersion::Draft09),
147 10 => Some(DraftVersion::Draft10),
148 11 => Some(DraftVersion::Draft11),
149 12 => Some(DraftVersion::Draft12),
150 13 => Some(DraftVersion::Draft13),
151 14 => Some(DraftVersion::Draft14),
152 15 => Some(DraftVersion::Draft15),
153 16 => Some(DraftVersion::Draft16),
154 17 => Some(DraftVersion::Draft17),
155 18 => Some(DraftVersion::Draft18),
156 19 => Some(DraftVersion::Draft19),
157 20 => Some(DraftVersion::Draft20),
158 _ => None,
159 }
160 }
161
162 pub fn uses_fixed_length_framing(&self) -> bool {
167 self.number() >= 11
168 }
169
170 pub fn varint_encoding(&self) -> VarIntEncoding {
178 match self {
179 DraftVersion::Draft07
180 | DraftVersion::Draft08
181 | DraftVersion::Draft09
182 | DraftVersion::Draft10
183 | DraftVersion::Draft11
184 | DraftVersion::Draft12
185 | DraftVersion::Draft13
186 | DraftVersion::Draft14
187 | DraftVersion::Draft15
188 | DraftVersion::Draft16 => VarIntEncoding::Rfc9000,
189 DraftVersion::Draft17 => VarIntEncoding::Moqt17,
190 DraftVersion::Draft18 | DraftVersion::Draft19 | DraftVersion::Draft20 => {
195 VarIntEncoding::Moqt18
196 }
197 }
198 }
199
200 pub fn uses_moqt_varint(&self) -> bool {
203 self.varint_encoding() != VarIntEncoding::Rfc9000
204 }
205
206 pub fn varint_len(&self, first_byte: u8) -> usize {
215 match self.varint_encoding() {
216 VarIntEncoding::Rfc9000 => 1 << (first_byte >> 6),
217 VarIntEncoding::Moqt17 | VarIntEncoding::Moqt18 => {
218 if first_byte == 0xFF {
219 9
220 } else {
221 first_byte.leading_ones() as usize + 1
222 }
223 }
224 }
225 }
226
227 pub fn decode_varint(&self, buf: &mut impl Buf) -> Result<VarInt, VarIntError> {
229 match self.varint_encoding() {
230 VarIntEncoding::Rfc9000 => VarInt::decode(buf),
231 VarIntEncoding::Moqt17 => VarInt::decode_moqt::<Moqt17>(buf),
232 VarIntEncoding::Moqt18 => VarInt::decode_moqt::<Moqt18>(buf),
233 }
234 }
235
236 pub fn encode_varint(&self, value: VarInt, buf: &mut impl BufMut) {
238 match self.varint_encoding() {
239 VarIntEncoding::Rfc9000 => value.encode(buf),
240 VarIntEncoding::Moqt17 => value.encode_moqt::<Moqt17>(buf),
241 VarIntEncoding::Moqt18 => value.encode_moqt::<Moqt18>(buf),
242 }
243 }
244
245 pub fn number(&self) -> u8 {
247 match self {
248 DraftVersion::Draft07 => 7,
249 DraftVersion::Draft08 => 8,
250 DraftVersion::Draft09 => 9,
251 DraftVersion::Draft10 => 10,
252 DraftVersion::Draft11 => 11,
253 DraftVersion::Draft12 => 12,
254 DraftVersion::Draft13 => 13,
255 DraftVersion::Draft14 => 14,
256 DraftVersion::Draft15 => 15,
257 DraftVersion::Draft16 => 16,
258 DraftVersion::Draft17 => 17,
259 DraftVersion::Draft18 => 18,
260 DraftVersion::Draft19 => 19,
261 DraftVersion::Draft20 => 20,
262 }
263 }
264}
265
266impl std::fmt::Display for DraftVersion {
267 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
268 write!(f, "draft-{:02}", self.number())
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use super::*;
275
276 #[test]
279 fn every_draft_states_its_varint_encoding() {
280 use VarIntEncoding::*;
281 let expected = [
282 (DraftVersion::Draft07, Rfc9000),
283 (DraftVersion::Draft08, Rfc9000),
284 (DraftVersion::Draft09, Rfc9000),
285 (DraftVersion::Draft10, Rfc9000),
286 (DraftVersion::Draft11, Rfc9000),
287 (DraftVersion::Draft12, Rfc9000),
288 (DraftVersion::Draft13, Rfc9000),
289 (DraftVersion::Draft14, Rfc9000),
290 (DraftVersion::Draft15, Rfc9000),
291 (DraftVersion::Draft16, Rfc9000),
292 (DraftVersion::Draft17, Moqt17),
293 (DraftVersion::Draft18, Moqt18),
294 (DraftVersion::Draft19, Moqt18),
295 (DraftVersion::Draft20, Moqt18),
296 ];
297 for (draft, encoding) in expected {
298 assert_eq!(draft.varint_encoding(), encoding, "{draft}");
299 assert_eq!(draft.uses_moqt_varint(), encoding != Rfc9000, "{draft}");
300 }
301 }
302
303 #[test]
306 fn varint_len_and_round_trip_follow_the_encoding() {
307 let mut buf = Vec::new();
308 DraftVersion::Draft14.encode_varint(VarInt::from_usize(5000), &mut buf);
309 assert_eq!(buf, vec![0x53, 0x88]);
310 assert_eq!(DraftVersion::Draft14.varint_len(buf[0]), 2);
311
312 let mut buf = Vec::new();
313 DraftVersion::Draft20.encode_varint(VarInt::from_usize(5000), &mut buf);
314 assert_eq!(buf, vec![0x93, 0x88]);
315 assert_eq!(DraftVersion::Draft20.varint_len(buf[0]), 2);
316
317 assert_eq!(DraftVersion::Draft14.varint_len(0x40), 2);
320 assert_eq!(DraftVersion::Draft20.varint_len(0x40), 1);
321 }
322
323 #[test]
324 fn from_alpn_resolves_drafts_15_plus() {
325 assert_eq!(DraftVersion::from_alpn(b"moqt-15"), Some(DraftVersion::Draft15));
326 assert_eq!(DraftVersion::from_alpn(b"moqt-16"), Some(DraftVersion::Draft16));
327 assert_eq!(DraftVersion::from_alpn(b"moqt-17"), Some(DraftVersion::Draft17));
328 assert_eq!(DraftVersion::from_alpn(b"moqt-18"), Some(DraftVersion::Draft18));
329 assert_eq!(DraftVersion::from_alpn(b"moqt-19"), Some(DraftVersion::Draft19));
330 assert_eq!(DraftVersion::from_alpn(b"moqt-20"), Some(DraftVersion::Draft20));
331 }
332
333 #[test]
334 fn from_alpn_none_for_moq_00_and_unknown() {
335 assert_eq!(DraftVersion::from_alpn(b"moq-00"), None);
336 assert_eq!(DraftVersion::from_alpn(b"h3"), None);
337 assert_eq!(DraftVersion::from_alpn(b""), None);
338 assert_eq!(DraftVersion::from_alpn(b"moqt-99"), None);
339 }
340
341 #[test]
342 fn from_alpn_round_trips_with_quic_alpn() {
343 for d in [
344 DraftVersion::Draft15,
345 DraftVersion::Draft16,
346 DraftVersion::Draft17,
347 DraftVersion::Draft18,
348 DraftVersion::Draft19,
349 DraftVersion::Draft20,
350 ] {
351 assert_eq!(DraftVersion::from_alpn(d.quic_alpn()), Some(d));
352 }
353 }
354
355 #[test]
356 fn from_number_resolves_supported_range() {
357 for n in 7..=20u8 {
358 assert!(DraftVersion::from_number(n).is_some(), "draft {n} should resolve");
359 }
360 }
361
362 #[test]
363 fn from_number_none_outside_range() {
364 assert_eq!(DraftVersion::from_number(0), None);
365 assert_eq!(DraftVersion::from_number(6), None);
366 assert_eq!(DraftVersion::from_number(21), None);
367 assert_eq!(DraftVersion::from_number(255), None);
368 }
369}