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