async_httplib/
version.rs

1use std::fmt::{self, Display};
2use std::cmp::Ordering;
3use std::io::{Error, ErrorKind};
4use std::str::FromStr;
5
6#[derive(Debug, Clone, Copy, Eq, Hash)]
7pub enum Version {
8    Http0_9 = 9,
9    Http1_0 = 10,
10    Http1_1 = 11,
11    Http2_0 = 20,
12    Http3_0 = 30,
13}
14
15impl Display for Version {
16
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        match self {
19            Self::Http0_9 => write!(f, "HTTP/0.9"),
20            Self::Http1_0 => write!(f, "HTTP/1.0"),
21            Self::Http1_1 => write!(f, "HTTP/1.1"),
22            Self::Http2_0 => write!(f, "HTTP/2"),
23            Self::Http3_0 => write!(f, "HTTP/3"),
24        }
25    }
26}
27
28impl FromStr for Version {
29    type Err = Error;
30
31    fn from_str(v: &str) -> Result<Self, Self::Err> {
32        match v {
33            "HTTP/0.9" => Ok(Self::Http0_9),
34            "0.9" => Ok(Self::Http0_9),
35            "HTTP/1.0" => Ok(Self::Http1_0),
36            "1.0" => Ok(Self::Http1_0),
37            "HTTP/1.1" => Ok(Self::Http1_1),
38            "1.1" => Ok(Self::Http1_1),
39            "1" => Ok(Self::Http1_1),
40            "HTTP/2" => Ok(Self::Http2_0),
41            "2.0" => Ok(Self::Http2_0),
42            "2" => Ok(Self::Http2_0),
43            "HTTP/3" => Ok(Self::Http3_0),
44            "3.0" => Ok(Self::Http3_0),
45            "3" => Ok(Self::Http3_0),
46            v => Err(Error::new(ErrorKind::InvalidInput, format!("The version `{}` is invalid.", v))),
47        }
48    }
49}
50
51impl<'a> std::convert::TryFrom<&[u8]> for Version {
52    type Error = Error;
53
54    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
55        match String::from_utf8(bytes.to_vec()) {
56            Ok(txt) => Self::from_str(&txt),
57            Err(e) => Err(Error::new(ErrorKind::InvalidInput, e.to_string())),
58        }
59    }
60}
61
62impl PartialOrd for Version {
63    fn partial_cmp(&self, other: &Version) -> Option<Ordering> {
64        Some(self.cmp(other))
65    }
66}
67
68impl Ord for Version {
69    fn cmp(&self, other: &Version) -> Ordering {
70        (*self as usize).cmp(&(*other as usize))
71    }
72}
73
74impl PartialEq for Version {
75    fn eq(&self, other: &Version) -> bool {
76        (*self as usize) == (*other as usize)
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83    use std::convert::TryFrom;
84
85    #[test]
86    fn implements_from_str() {
87        let version = Version::from_str("1.1").unwrap();
88        assert_eq!(version, Version::Http1_1);
89    }
90
91    #[test]
92    fn implements_try_from() {
93        let version = Version::try_from("1.1".as_bytes()).unwrap();
94        assert_eq!(version, Version::Http1_1);
95    }
96
97    #[test]
98    fn implements_to_string() {
99        let version = Version::from_str("2.0").unwrap();
100        assert_eq!(version.to_string(), "HTTP/2");
101    }
102
103    #[test]
104    fn implements_ordering() {
105        assert!(Version::Http1_1 > Version::Http0_9);
106        assert!(Version::Http0_9 < Version::Http1_0);
107        assert!(Version::Http1_0 == Version::Http1_0);
108    }
109}