1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 //! HTTP [`Version`]. 15 //! 16 //! HTTP's version number consists of two decimal digits separated by a "." 17 //! (period or decimal point). The first digit (major version) indicates the 18 //! messaging syntax, whereas the second digit (minor version) indicates the 19 //! highest minor version within that major version to which the sender is 20 //! conformant (able to understand for future communication). 21 //! 22 //! [`Version`]: https://httpwg.org/specs/rfc9110.html#protocol.version 23 24 use core::convert::TryFrom; 25 26 use crate::error::{ErrorKind, HttpError}; 27 28 /// HTTP [`Version`] implementation. 29 /// 30 /// [`Version`]: https://httpwg.org/specs/rfc9110.html#protocol.version 31 /// 32 /// # Examples 33 /// 34 /// ``` 35 /// use ylong_http::version::Version; 36 /// 37 /// assert_eq!(Version::HTTP1_1.as_str(), "HTTP/1.1"); 38 /// ``` 39 #[derive(Clone, Debug, PartialEq, Eq)] 40 pub struct Version(Inner); 41 42 impl Version { 43 /// HTTP/1.0 44 pub const HTTP1_0: Self = Self(Inner::Http10); 45 /// HTTP/1.1 46 pub const HTTP1_1: Self = Self(Inner::Http11); 47 /// HTTP/2 48 pub const HTTP2: Self = Self(Inner::Http2); 49 /// HTTP/3 50 pub const HTTP3: Self = Self(Inner::Http3); 51 52 /// Converts a `Version` to a `&str`. 53 /// 54 /// # Examples 55 /// 56 /// ``` 57 /// use ylong_http::version::Version; 58 /// 59 /// assert_eq!(Version::HTTP1_1.as_str(), "HTTP/1.1"); 60 /// ``` as_str(&self) -> &str61 pub fn as_str(&self) -> &str { 62 match self.0 { 63 Inner::Http10 => "HTTP/1.0", 64 Inner::Http11 => "HTTP/1.1", 65 Inner::Http2 => "HTTP/2.0", 66 Inner::Http3 => "HTTP/3.0", 67 } 68 } 69 } 70 71 impl<'a> TryFrom<&'a str> for Version { 72 type Error = HttpError; 73 try_from(str: &'a str) -> Result<Self, Self::Error>74 fn try_from(str: &'a str) -> Result<Self, Self::Error> { 75 match str { 76 "HTTP/1.0" => Ok(Version::HTTP1_0), 77 "HTTP/1.1" => Ok(Version::HTTP1_1), 78 "HTTP/2.0" => Ok(Version::HTTP2), 79 "HTTP/3.0" => Ok(Version::HTTP3), 80 _ => Err(ErrorKind::InvalidInput.into()), 81 } 82 } 83 } 84 85 #[derive(Clone, Debug, PartialEq, Eq)] 86 enum Inner { 87 Http10, 88 Http11, 89 Http2, 90 Http3, 91 } 92 93 #[cfg(test)] 94 mod ut_version { 95 use std::convert::TryFrom; 96 97 use super::Version; 98 99 /// UT test cases for `Version::as_str`. 100 /// 101 /// # Brief 102 /// 1. Checks whether `Version::as_str` is correct. 103 #[test] ut_version_as_str()104 fn ut_version_as_str() { 105 assert_eq!(Version::HTTP1_0.as_str(), "HTTP/1.0"); 106 assert_eq!(Version::HTTP1_1.as_str(), "HTTP/1.1"); 107 assert_eq!(Version::HTTP2.as_str(), "HTTP/2.0"); 108 assert_eq!(Version::HTTP3.as_str(), "HTTP/3.0"); 109 } 110 111 /// UT test cases for `Version::try_from`. 112 /// 113 /// # Brief 114 /// 1. Checks whether `Version::try_from` is correct. 115 #[test] ut_version_try_from()116 fn ut_version_try_from() { 117 assert_eq!(Version::try_from("HTTP/1.0").unwrap(), Version::HTTP1_0); 118 assert_eq!(Version::try_from("HTTP/1.1").unwrap(), Version::HTTP1_1); 119 assert_eq!(Version::try_from("HTTP/2.0").unwrap(), Version::HTTP2); 120 assert_eq!(Version::try_from("HTTP/3.0").unwrap(), Version::HTTP3); 121 assert!(Version::try_from("http/1.0").is_err()); 122 assert!(Version::try_from("http/1.1").is_err()); 123 assert!(Version::try_from("http/2.0").is_err()); 124 assert!(Version::try_from("http/3.0").is_err()); 125 } 126 } 127