Skip to main content

reqtls/
alpn.rs

1use std::fmt::Display;
2use crate::error::RlsResult;
3use crate::WriteExt;
4
5#[derive(Debug, PartialEq, Clone)]
6pub enum ALPN {
7    Http20,
8    Http11,
9    Http10,
10    Custom(Vec<u8>),
11}
12
13impl ALPN {
14    pub fn from_slice(opt: &[u8]) -> ALPN {
15        match opt {
16            b"http/1.0" => ALPN::Http10,
17            b"http/1.1" => ALPN::Http11,
18            b"h2" => ALPN::Http20,
19            _ => ALPN::Custom(opt.to_vec()),
20        }
21    }
22
23    pub fn value(&self) -> &str {
24        match self {
25            ALPN::Http10 => "http/1.0",
26            ALPN::Http11 => "http/1.1",
27            ALPN::Http20 => "h2",
28            ALPN::Custom(v) => unsafe { std::str::from_utf8_unchecked(v.as_slice()) }
29        }
30    }
31
32    pub fn from_bytes(bytes: &[u8]) -> RlsResult<Vec<ALPN>> {
33        let mut res = vec![];
34        let mut index = 0;
35        while index < bytes.len() {
36            let len = bytes[index] as usize;
37            res.push(ALPN::from_slice(&bytes[index + 1..len + index + 1]));
38            index = index + 1 + len;
39        }
40        Ok(res)
41    }
42
43    pub fn is_empty(&self) -> bool { self.len() == 0 }
44
45    pub fn len(&self) -> usize { 1 + self.value().len() }
46
47    pub fn write_to<W: WriteExt>(self, writer: &mut W) {
48        writer.write_u8(self.value().len() as u8);
49        writer.write_slice(self.value().as_bytes());
50    }
51}
52
53impl Display for ALPN {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        match self {
56            ALPN::Http20 => write!(f, "HTTP/2.0"),
57            ALPN::Http11 => write!(f, "HTTP/1.1"),
58            ALPN::Http10 => write!(f, "HTTP/1.0"),
59            ALPN::Custom(v) => write!(f, "{}", String::from_utf8_lossy(v)),
60        }
61    }
62}