Skip to content

Commit

Permalink
Auto merge of #29190 - alexcrichton:from-str-socket-addr, r=brson
Browse files Browse the repository at this point in the history
This was already implemented for SocketAddr, so the other types are lacking it
is just an oversight!

Closes #29183
  • Loading branch information
bors committed Oct 21, 2015
2 parents fddf2f7 + 8aa6a11 commit ff5cc89
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 17 deletions.
8 changes: 8 additions & 0 deletions src/libstd/net/ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,18 @@ mod tests {
fn test_from_str_socket_addr() {
assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)),
"77.88.21.11:80".parse());
assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)),
"77.88.21.11:80".parse());
assert_eq!(Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
"[2a02:6b8:0:1::1]:53".parse());
assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1,
0, 0, 0, 1), 53, 0, 0)),
"[2a02:6b8:0:1::1]:53".parse());
assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
"[::127.0.0.1]:22".parse());
assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0,
0x7F00, 1), 22, 0, 0)),
"[::127.0.0.1]:22".parse());

// without port
let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
Expand Down
68 changes: 51 additions & 17 deletions src/libstd/net/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,30 +267,42 @@ impl<'a> Parser<'a> {
self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
}

fn read_socket_addr(&mut self) -> Option<SocketAddr> {
fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
let colon = |p: &mut Parser| p.read_given_char(':');
let port = |p: &mut Parser| {
p.read_number(10, 5, 0x10000).map(|n| n as u16)
};

self.read_seq_3(ip_addr, colon, port).map(|t| {
let (ip, _, port): (Ipv4Addr, char, u16) = t;
SocketAddrV4::new(ip, port)
})
}

fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> {
let ip_addr = |p: &mut Parser| {
let ipv4_p = |p: &mut Parser| p.read_ip_addr();
let ipv6_p = |p: &mut Parser| {
let open_br = |p: &mut Parser| p.read_given_char('[');
let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
let clos_br = |p: &mut Parser| p.read_given_char(']');
p.read_seq_3::<char, Ipv6Addr, char, _, _, _>(open_br, ip_addr, clos_br)
.map(|t| match t { (_, ip, _) => IpAddr::V6(ip) })
};
p.read_or(&mut [Box::new(ipv4_p), Box::new(ipv6_p)])
let open_br = |p: &mut Parser| p.read_given_char('[');
let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
let clos_br = |p: &mut Parser| p.read_given_char(']');
p.read_seq_3(open_br, ip_addr, clos_br).map(|t| t.1)
};
let colon = |p: &mut Parser| p.read_given_char(':');
let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
let port = |p: &mut Parser| {
p.read_number(10, 5, 0x10000).map(|n| n as u16)
};

// host, colon, port
self.read_seq_3(ip_addr, colon, port).map(|t| {
let (ip, _, port): (IpAddr, char, u16) = t;
match ip {
IpAddr::V4(ip) => SocketAddr::V4(SocketAddrV4::new(ip, port)),
IpAddr::V6(ip) => SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0)),
}
let (ip, _, port): (Ipv6Addr, char, u16) = t;
SocketAddrV6::new(ip, port, 0, 0)
})
}

fn read_socket_addr(&mut self) -> Option<SocketAddr> {
let v4 = |p: &mut Parser| p.read_socket_addr_v4().map(SocketAddr::V4);
let v6 = |p: &mut Parser| p.read_socket_addr_v6().map(SocketAddr::V6);
self.read_or(&mut [Box::new(v4), Box::new(v6)])
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -326,6 +338,28 @@ impl FromStr for Ipv6Addr {
}
}

#[stable(feature = "socket_addr_from_str", since = "1.5.0")]
impl FromStr for SocketAddrV4 {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> {
match Parser::new(s).read_till_eof(|p| p.read_socket_addr_v4()) {
Some(s) => Ok(s),
None => Err(AddrParseError(())),
}
}
}

#[stable(feature = "socket_addr_from_str", since = "1.5.0")]
impl FromStr for SocketAddrV6 {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> {
match Parser::new(s).read_till_eof(|p| p.read_socket_addr_v6()) {
Some(s) => Ok(s),
None => Err(AddrParseError(())),
}
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for SocketAddr {
type Err = AddrParseError;
Expand Down

0 comments on commit ff5cc89

Please sign in to comment.