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 /// HTTP1.1 44 pub const HTTP1_1: Self = Self(Inner::Http11); 45 /// HTTP2 46 pub const HTTP2: Self = Self(Inner::Http2); 47 /// HTTP3 48 pub const HTTP3: Self = Self(Inner::Http3); 49 50 /// Converts a `Version` to a `&str`. 51 /// 52 /// # Examples 53 /// 54 /// ``` 55 /// use ylong_http::version::Version; 56 /// 57 /// assert_eq!(Version::HTTP1_1.as_str(), "HTTP/1.1"); 58 /// ``` as_str(&self) -> &str59 pub fn as_str(&self) -> &str { 60 match self.0 { 61 Inner::Http11 => "HTTP/1.1", 62 Inner::Http2 => "HTTP/2.0", 63 Inner::Http3 => "HTTP/3.0", 64 } 65 } 66 } 67 68 impl<'a> TryFrom<&'a str> for Version { 69 type Error = HttpError; 70 try_from(str: &'a str) -> Result<Self, Self::Error>71 fn try_from(str: &'a str) -> Result<Self, Self::Error> { 72 match str { 73 "HTTP/1.1" => Ok(Version::HTTP1_1), 74 "HTTP/2.0" => Ok(Version::HTTP2), 75 "HTTP/3.0" => Ok(Version::HTTP3), 76 _ => Err(ErrorKind::InvalidInput.into()), 77 } 78 } 79 } 80 81 #[derive(Clone, Debug, PartialEq, Eq)] 82 enum Inner { 83 Http11, 84 Http2, 85 Http3, 86 } 87 88 #[cfg(test)] 89 mod ut_version { 90 use std::convert::TryFrom; 91 92 use super::Version; 93 94 /// UT test cases for `Version::as_str`. 95 /// 96 /// # Brief 97 /// 1. Checks whether `Version::as_str` is correct. 98 #[test] ut_version_as_str()99 fn ut_version_as_str() { 100 assert_eq!(Version::HTTP1_1.as_str(), "HTTP/1.1"); 101 assert_eq!(Version::HTTP2.as_str(), "HTTP/2.0"); 102 assert_eq!(Version::HTTP3.as_str(), "HTTP/3.0"); 103 } 104 105 /// UT test cases for `Version::try_from`. 106 /// 107 /// # Brief 108 /// 1. Checks whether `Version::try_from` is correct. 109 #[test] ut_version_try_from()110 fn ut_version_try_from() { 111 assert_eq!(Version::try_from("HTTP/1.1").unwrap(), Version::HTTP1_1); 112 assert_eq!(Version::try_from("HTTP/2.0").unwrap(), Version::HTTP2); 113 assert_eq!(Version::try_from("HTTP/3.0").unwrap(), Version::HTTP3); 114 assert!(Version::try_from("http/1.1").is_err()); 115 assert!(Version::try_from("http/2.0").is_err()); 116 assert!(Version::try_from("http/3.0").is_err()); 117 } 118 } 119