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