1 use std::fmt;
2 
3 use super::{ErrorKind, InvalidUri};
4 
5 /// The port component of a URI.
6 pub struct Port<T> {
7     port: u16,
8     repr: T,
9 }
10 
11 impl<T> Port<T> {
12     /// Returns the port number as a `u16`.
13     ///
14     /// # Examples
15     ///
16     /// Port as `u16`.
17     ///
18     /// ```
19     /// # use http::uri::Authority;
20     /// let authority: Authority = "example.org:80".parse().unwrap();
21     ///
22     /// let port = authority.port().unwrap();
23     /// assert_eq!(port.as_u16(), 80);
24     /// ```
as_u16(&self) -> u1625     pub fn as_u16(&self) -> u16 {
26         self.port
27     }
28 }
29 
30 impl<T> Port<T>
31 where
32     T: AsRef<str>,
33 {
34     /// Converts a `str` to a port number.
35     ///
36     /// The supplied `str` must be a valid u16.
from_str(bytes: T) -> Result<Self, InvalidUri>37     pub(crate) fn from_str(bytes: T) -> Result<Self, InvalidUri> {
38         bytes
39             .as_ref()
40             .parse::<u16>()
41             .map(|port| Port { port, repr: bytes })
42             .map_err(|_| ErrorKind::InvalidPort.into())
43     }
44 
45     /// Returns the port number as a `str`.
46     ///
47     /// # Examples
48     ///
49     /// Port as `str`.
50     ///
51     /// ```
52     /// # use http::uri::Authority;
53     /// let authority: Authority = "example.org:80".parse().unwrap();
54     ///
55     /// let port = authority.port().unwrap();
56     /// assert_eq!(port.as_str(), "80");
57     /// ```
as_str(&self) -> &str58     pub fn as_str(&self) -> &str {
59         self.repr.as_ref()
60     }
61 }
62 
63 impl<T> fmt::Debug for Port<T>
64 where
65     T: fmt::Debug,
66 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result67     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68         f.debug_tuple("Port").field(&self.port).finish()
69     }
70 }
71 
72 impl<T> fmt::Display for Port<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result73     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74         // Use `u16::fmt` so that it respects any formatting flags that
75         // may have been set (like padding, align, etc).
76         fmt::Display::fmt(&self.port, f)
77     }
78 }
79 
80 impl<T> From<Port<T>> for u16 {
from(port: Port<T>) -> Self81     fn from(port: Port<T>) -> Self {
82         port.as_u16()
83     }
84 }
85 
86 impl<T> AsRef<str> for Port<T>
87 where
88     T: AsRef<str>,
89 {
as_ref(&self) -> &str90     fn as_ref(&self) -> &str {
91         self.as_str()
92     }
93 }
94 
95 impl<T, U> PartialEq<Port<U>> for Port<T> {
eq(&self, other: &Port<U>) -> bool96     fn eq(&self, other: &Port<U>) -> bool {
97         self.port == other.port
98     }
99 }
100 
101 impl<T> PartialEq<u16> for Port<T> {
eq(&self, other: &u16) -> bool102     fn eq(&self, other: &u16) -> bool {
103         self.port == *other
104     }
105 }
106 
107 impl<T> PartialEq<Port<T>> for u16 {
eq(&self, other: &Port<T>) -> bool108     fn eq(&self, other: &Port<T>) -> bool {
109         other.port == *self
110     }
111 }
112 
113 #[cfg(test)]
114 mod tests {
115     use super::*;
116 
117     #[test]
partialeq_port()118     fn partialeq_port() {
119         let port_a = Port::from_str("8080").unwrap();
120         let port_b = Port::from_str("8080").unwrap();
121         assert_eq!(port_a, port_b);
122     }
123 
124     #[test]
partialeq_port_different_reprs()125     fn partialeq_port_different_reprs() {
126         let port_a = Port {
127             repr: "8081",
128             port: 8081,
129         };
130         let port_b = Port {
131             repr: String::from("8081"),
132             port: 8081,
133         };
134         assert_eq!(port_a, port_b);
135         assert_eq!(port_b, port_a);
136     }
137 
138     #[test]
partialeq_u16()139     fn partialeq_u16() {
140         let port = Port::from_str("8080").unwrap();
141         // test equals in both directions
142         assert_eq!(port, 8080);
143         assert_eq!(8080, port);
144     }
145 
146     #[test]
u16_from_port()147     fn u16_from_port() {
148         let port = Port::from_str("8080").unwrap();
149         assert_eq!(8080, u16::from(port));
150     }
151 }
152