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