Skip to content

Commit

Permalink
change Port<'a> to be Port<Repr>
Browse files Browse the repository at this point in the history
Closes #263
  • Loading branch information
seanmonstar committed Oct 18, 2018
1 parent 4a71708 commit c434895
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 29 deletions.
4 changes: 2 additions & 2 deletions src/uri/authority.rs
Expand Up @@ -181,7 +181,7 @@ impl Authority {
host(self.as_str())
}

#[deprecated(since="0.2.0", note="please use `port_part` instead")]
#[deprecated(since="0.1.14", note="use `port_part` instead")]
#[doc(hidden)]
pub fn port(&self) -> Option<u16> {
self.port_part().and_then(|p| Some(p.as_u16()))
Expand Down Expand Up @@ -221,7 +221,7 @@ impl Authority {
///
/// assert!(authority.port_part().is_none());
/// ```
pub fn port_part(&self) -> Option<Port> {
pub fn port_part(&self) -> Option<Port<&str>> {
let bytes = self.as_str();
bytes
.rfind(":")
Expand Down
6 changes: 4 additions & 2 deletions src/uri/mod.rs
Expand Up @@ -137,6 +137,7 @@ enum ErrorKind {
InvalidUriChar,
InvalidScheme,
InvalidAuthority,
InvalidPort,
InvalidFormat,
SchemeMissing,
AuthorityMissing,
Expand Down Expand Up @@ -568,7 +569,7 @@ impl Uri {
self.authority_part().map(|a| a.host())
}

#[deprecated(since="0.2.0", note="please use `port_part` instead")]
#[deprecated(since="0.1.14", note="use `port_part` instead")]
#[doc(hidden)]
pub fn port(&self) -> Option<u16> {
self.port_part().and_then(|p| Some(p.as_u16()))
Expand Down Expand Up @@ -617,7 +618,7 @@ impl Uri {
///
/// assert!(uri.port_part().is_none());
/// ```
pub fn port_part(&self) -> Option<Port> {
pub fn port_part(&self) -> Option<Port<&str>> {
self.authority_part()
.and_then(|a| a.port_part())
}
Expand Down Expand Up @@ -1045,6 +1046,7 @@ impl Error for InvalidUri {
ErrorKind::InvalidUriChar => "invalid uri character",
ErrorKind::InvalidScheme => "invalid scheme",
ErrorKind::InvalidAuthority => "invalid authority",
ErrorKind::InvalidPort => "invalid port",
ErrorKind::InvalidFormat => "invalid format",
ErrorKind::SchemeMissing => "scheme missing",
ErrorKind::AuthorityMissing => "authority missing",
Expand Down
102 changes: 77 additions & 25 deletions src/uri/port.rs
@@ -1,21 +1,14 @@
use std::{fmt, num};
use std::str::FromStr;
use std::fmt;

use super::{ErrorKind, InvalidUri};

/// The port component of a URI.
#[derive(Debug)]
pub struct Port<'a> {
bytes: &'a str,
pub struct Port<T> {
port: u16,
repr: T,
}

impl<'a> Port<'a> {
/// Converts a `str` to a port number.
///
/// The supplied `str` must be a valid u16.
pub(crate) fn from_str(bytes: &'a str) -> Result<Self, num::ParseIntError> {
u16::from_str(bytes).and_then(|port| Ok(Port { port, bytes }))
}

impl<T> Port<T> {
/// Returns the port number as a `u16`.
///
/// # Examples
Expand All @@ -32,6 +25,27 @@ impl<'a> Port<'a> {
pub fn as_u16(&self) -> u16 {
self.port
}
}

impl<T> Port<T>
where
T: AsRef<str>,
{
/// Converts a `str` to a port number.
///
/// The supplied `str` must be a valid u16.
pub(crate) fn from_str(bytes: T) -> Result<Self, InvalidUri> {
bytes
.as_ref()
.parse::<u16>()
.map(|port| Port {
port,
repr: bytes,
})
.map_err(|_| {
ErrorKind::InvalidPort.into()
})
}

/// Returns the port number as a `str`.
///
Expand All @@ -46,41 +60,63 @@ impl<'a> Port<'a> {
/// let port = authority.port_part().unwrap();
/// assert_eq!(port.as_str(), "80");
/// ```
pub fn as_str(&self) -> &'a str {
self.bytes
pub fn as_str(&self) -> &str {
self.repr.as_ref()
}
}

impl<T> fmt::Debug for Port<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("Port")
.field(&self.port)
.finish()
}
}

impl<'a> fmt::Display for Port<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.bytes)
impl<T> fmt::Display for Port<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Use `u16::fmt` so that it respects any formatting flags that
// may have been set (like padding, align, etc).
fmt::Display::fmt(&self.port, f)
}
}

impl<'a> From<Port<'a>> for u16 {
fn from(port: Port) -> Self {
impl<T> From<Port<T>> for u16 {
fn from(port: Port<T>) -> Self {
port.as_u16()
}
}

impl<'a> AsRef<str> for Port<'a> {
impl<T> AsRef<str> for Port<T>
where
T: AsRef<str>,
{
fn as_ref(&self) -> &str {
self.as_str()
}
}

impl<'a> PartialEq for Port<'a> {
fn eq(&self, other: &Self) -> bool {
impl<T, U> PartialEq<Port<U>> for Port<T> {
fn eq(&self, other: &Port<U>) -> bool {
self.port == other.port
}
}

impl<'a> PartialEq<u16> for Port<'a> {
impl<T> PartialEq<u16> for Port<T> {
fn eq(&self, other: &u16) -> bool {
self.port == *other
}
}

impl<T> PartialEq<Port<T>> for u16 {
fn eq(&self, other: &Port<T>) -> bool {
other.port == *self
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -92,10 +128,26 @@ mod tests {
assert_eq!(port_a, port_b);
}

#[test]
fn partialeq_port_different_reprs() {
let port_a = Port {
repr: "8081",
port: 8081,
};
let port_b = Port {
repr: String::from("8081"),
port: 8081,
};
assert_eq!(port_a, port_b);
assert_eq!(port_b, port_a);
}

#[test]
fn partialeq_u16() {
let port = Port::from_str("8080").unwrap();
assert_eq!(port, 8080u16);
// test equals in both directions
assert_eq!(port, 8080);
assert_eq!(8080, port);
}

#[test]
Expand Down

0 comments on commit c434895

Please sign in to comment.