2013-04-17 17:55:21 -07:00
|
|
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
2013-11-10 22:46:32 -08:00
|
|
|
use container::Container;
|
2013-08-05 21:15:55 +04:00
|
|
|
use from_str::FromStr;
|
2014-01-06 16:48:51 -08:00
|
|
|
use iter::Iterator;
|
2013-08-05 21:15:55 +04:00
|
|
|
use option::{Option, None, Some};
|
2014-01-06 16:48:51 -08:00
|
|
|
use str::StrSlice;
|
2013-11-10 22:46:32 -08:00
|
|
|
use to_str::ToStr;
|
2014-02-10 02:21:50 -08:00
|
|
|
use to_bytes::IterBytes;
|
2014-01-06 16:48:51 -08:00
|
|
|
use vec::{MutableCloneableVector, ImmutableVector, MutableVector};
|
2013-07-25 18:18:43 -04:00
|
|
|
|
2013-09-26 21:22:22 -07:00
|
|
|
pub type Port = u16;
|
2013-06-25 16:03:24 -07:00
|
|
|
|
2014-02-10 02:21:50 -08:00
|
|
|
#[deriving(Eq, TotalEq, Clone, IterBytes)]
|
2013-04-17 17:55:21 -07:00
|
|
|
pub enum IpAddr {
|
2013-08-03 02:06:24 +04:00
|
|
|
Ipv4Addr(u8, u8, u8, u8),
|
|
|
|
|
Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16)
|
2013-04-17 17:55:21 -07:00
|
|
|
}
|
2013-07-25 18:18:43 -04:00
|
|
|
|
|
|
|
|
impl ToStr for IpAddr {
|
|
|
|
|
fn to_str(&self) -> ~str {
|
|
|
|
|
match *self {
|
2013-08-03 02:06:24 +04:00
|
|
|
Ipv4Addr(a, b, c, d) =>
|
2013-09-27 17:02:31 -07:00
|
|
|
format!("{}.{}.{}.{}", a, b, c, d),
|
2013-07-25 18:18:43 -04:00
|
|
|
|
|
|
|
|
// Ipv4 Compatible address
|
2013-08-03 02:06:24 +04:00
|
|
|
Ipv6Addr(0, 0, 0, 0, 0, 0, g, h) => {
|
2013-09-27 17:02:31 -07:00
|
|
|
format!("::{}.{}.{}.{}", (g >> 8) as u8, g as u8,
|
|
|
|
|
(h >> 8) as u8, h as u8)
|
2013-07-25 18:18:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ipv4-Mapped address
|
2013-08-09 13:53:28 +04:00
|
|
|
Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, g, h) => {
|
2013-09-27 17:02:31 -07:00
|
|
|
format!("::FFFF:{}.{}.{}.{}", (g >> 8) as u8, g as u8,
|
|
|
|
|
(h >> 8) as u8, h as u8)
|
2013-07-25 18:18:43 -04:00
|
|
|
}
|
|
|
|
|
|
2013-08-03 02:06:24 +04:00
|
|
|
Ipv6Addr(a, b, c, d, e, f, g, h) =>
|
2013-11-25 07:55:58 +02:00
|
|
|
format!("{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}", a, b, c, d, e, f, g, h)
|
2013-08-03 02:06:24 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-10 02:21:50 -08:00
|
|
|
#[deriving(Eq, TotalEq, Clone, IterBytes)]
|
2013-08-03 02:06:24 +04:00
|
|
|
pub struct SocketAddr {
|
|
|
|
|
ip: IpAddr,
|
|
|
|
|
port: Port,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl ToStr for SocketAddr {
|
|
|
|
|
fn to_str(&self) -> ~str {
|
|
|
|
|
match self.ip {
|
2013-11-28 12:22:53 -08:00
|
|
|
Ipv4Addr(..) => format!("{}:{}", self.ip.to_str(), self.port),
|
|
|
|
|
Ipv6Addr(..) => format!("[{}]:{}", self.ip.to_str(), self.port),
|
2013-07-25 18:18:43 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-08-05 21:15:55 +04:00
|
|
|
|
2013-12-09 23:16:18 -08:00
|
|
|
struct Parser<'a> {
|
2013-08-05 21:15:55 +04:00
|
|
|
// parsing as ASCII, so can use byte array
|
2013-12-09 23:16:18 -08:00
|
|
|
s: &'a [u8],
|
2013-08-05 21:15:55 +04:00
|
|
|
pos: uint,
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-09 23:16:18 -08:00
|
|
|
impl<'a> Parser<'a> {
|
|
|
|
|
fn new(s: &'a str) -> Parser<'a> {
|
2013-08-05 21:15:55 +04:00
|
|
|
Parser {
|
|
|
|
|
s: s.as_bytes(),
|
|
|
|
|
pos: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_eof(&self) -> bool {
|
|
|
|
|
self.pos == self.s.len()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Commit only if parser returns Some
|
2013-11-18 21:15:42 -08:00
|
|
|
fn read_atomically<T>(&mut self, cb: |&mut Parser| -> Option<T>)
|
|
|
|
|
-> Option<T> {
|
2013-08-05 21:15:55 +04:00
|
|
|
let pos = self.pos;
|
|
|
|
|
let r = cb(self);
|
|
|
|
|
if r.is_none() {
|
|
|
|
|
self.pos = pos;
|
|
|
|
|
}
|
|
|
|
|
r
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Commit only if parser read till EOF
|
2013-11-18 21:15:42 -08:00
|
|
|
fn read_till_eof<T>(&mut self, cb: |&mut Parser| -> Option<T>)
|
|
|
|
|
-> Option<T> {
|
2013-11-20 14:17:12 -08:00
|
|
|
self.read_atomically(|p| cb(p).filtered(|_| p.is_eof()))
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return result of first successful parser
|
2013-11-18 21:15:42 -08:00
|
|
|
fn read_or<T>(&mut self, parsers: &[|&mut Parser| -> Option<T>])
|
|
|
|
|
-> Option<T> {
|
2013-08-05 21:15:55 +04:00
|
|
|
for pf in parsers.iter() {
|
|
|
|
|
match self.read_atomically(|p: &mut Parser| (*pf)(p)) {
|
|
|
|
|
Some(r) => return Some(r),
|
|
|
|
|
None => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply 3 parsers sequentially
|
2013-11-18 21:15:42 -08:00
|
|
|
fn read_seq_3<A,
|
|
|
|
|
B,
|
|
|
|
|
C>(
|
|
|
|
|
&mut self,
|
|
|
|
|
pa: |&mut Parser| -> Option<A>,
|
|
|
|
|
pb: |&mut Parser| -> Option<B>,
|
|
|
|
|
pc: |&mut Parser| -> Option<C>)
|
|
|
|
|
-> Option<(A, B, C)> {
|
2013-11-20 14:17:12 -08:00
|
|
|
self.read_atomically(|p| {
|
2013-08-05 21:15:55 +04:00
|
|
|
let a = pa(p);
|
|
|
|
|
let b = if a.is_some() { pb(p) } else { None };
|
|
|
|
|
let c = if b.is_some() { pc(p) } else { None };
|
|
|
|
|
match (a, b, c) {
|
|
|
|
|
(Some(a), Some(b), Some(c)) => Some((a, b, c)),
|
|
|
|
|
_ => None
|
|
|
|
|
}
|
2013-11-20 14:17:12 -08:00
|
|
|
})
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read next char
|
|
|
|
|
fn read_char(&mut self) -> Option<char> {
|
|
|
|
|
if self.is_eof() {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
let r = self.s[self.pos] as char;
|
|
|
|
|
self.pos += 1;
|
|
|
|
|
Some(r)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return char and advance iff next char is equal to requested
|
|
|
|
|
fn read_given_char(&mut self, c: char) -> Option<char> {
|
2013-11-20 14:17:12 -08:00
|
|
|
self.read_atomically(|p| {
|
2013-08-05 21:15:55 +04:00
|
|
|
p.read_char().filtered(|&next| next == c)
|
2013-11-20 14:17:12 -08:00
|
|
|
})
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read digit
|
|
|
|
|
fn read_digit(&mut self, radix: u8) -> Option<u8> {
|
|
|
|
|
fn parse_digit(c: char, radix: u8) -> Option<u8> {
|
2013-09-03 19:24:12 -04:00
|
|
|
let c = c as u8;
|
2013-08-05 21:15:55 +04:00
|
|
|
// assuming radix is either 10 or 16
|
2013-09-03 19:24:12 -04:00
|
|
|
if c >= '0' as u8 && c <= '9' as u8 {
|
2013-12-25 00:53:05 +01:00
|
|
|
Some(c - '0' as u8)
|
2013-09-03 19:24:12 -04:00
|
|
|
} else if radix > 10 && c >= 'a' as u8 && c < 'a' as u8 + (radix - 10) {
|
2013-12-25 00:53:05 +01:00
|
|
|
Some(c - 'a' as u8 + 10)
|
2013-09-03 19:24:12 -04:00
|
|
|
} else if radix > 10 && c >= 'A' as u8 && c < 'A' as u8 + (radix - 10) {
|
2013-12-25 00:53:05 +01:00
|
|
|
Some(c - 'A' as u8 + 10)
|
2013-08-05 21:15:55 +04:00
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-20 14:17:12 -08:00
|
|
|
self.read_atomically(|p| {
|
2013-09-11 12:52:17 -07:00
|
|
|
p.read_char().and_then(|c| parse_digit(c, radix))
|
2013-11-20 14:17:12 -08:00
|
|
|
})
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
|
|
|
|
|
let mut r = 0u32;
|
|
|
|
|
let mut digit_count = 0;
|
|
|
|
|
loop {
|
|
|
|
|
match self.read_digit(radix) {
|
|
|
|
|
Some(d) => {
|
|
|
|
|
r = r * (radix as u32) + (d as u32);
|
|
|
|
|
digit_count += 1;
|
|
|
|
|
if digit_count > max_digits || r >= upto {
|
|
|
|
|
return None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
if digit_count == 0 {
|
|
|
|
|
return None
|
|
|
|
|
} else {
|
|
|
|
|
return Some(r)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read number, failing if max_digits of number value exceeded
|
|
|
|
|
fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
|
2013-11-20 14:17:12 -08:00
|
|
|
self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn read_ipv4_addr_impl(&mut self) -> Option<IpAddr> {
|
|
|
|
|
let mut bs = [0u8, ..4];
|
|
|
|
|
let mut i = 0;
|
|
|
|
|
while i < 4 {
|
|
|
|
|
if i != 0 && self.read_given_char('.').is_none() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-20 02:08:47 -04:00
|
|
|
let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
|
2013-08-05 21:15:55 +04:00
|
|
|
match octet {
|
|
|
|
|
Some(d) => bs[i] = d,
|
|
|
|
|
None => return None,
|
|
|
|
|
};
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
Some(Ipv4Addr(bs[0], bs[1], bs[2], bs[3]))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read IPv4 address
|
|
|
|
|
fn read_ipv4_addr(&mut self) -> Option<IpAddr> {
|
2013-11-20 14:17:12 -08:00
|
|
|
self.read_atomically(|p| p.read_ipv4_addr_impl())
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn read_ipv6_addr_impl(&mut self) -> Option<IpAddr> {
|
|
|
|
|
fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr {
|
|
|
|
|
assert!(head.len() + tail.len() <= 8);
|
|
|
|
|
let mut gs = [0u16, ..8];
|
|
|
|
|
gs.copy_from(head);
|
|
|
|
|
gs.mut_slice(8 - tail.len(), 8).copy_from(tail);
|
|
|
|
|
Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) {
|
|
|
|
|
let mut i = 0;
|
|
|
|
|
while i < limit {
|
|
|
|
|
if i < limit - 1 {
|
2013-11-20 14:17:12 -08:00
|
|
|
let ipv4 = p.read_atomically(|p| {
|
2013-08-05 21:15:55 +04:00
|
|
|
if i == 0 || p.read_given_char(':').is_some() {
|
|
|
|
|
p.read_ipv4_addr()
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
2013-11-20 14:17:12 -08:00
|
|
|
});
|
2013-08-05 21:15:55 +04:00
|
|
|
match ipv4 {
|
|
|
|
|
Some(Ipv4Addr(a, b, c, d)) => {
|
|
|
|
|
groups[i + 0] = (a as u16 << 8) | (b as u16);
|
|
|
|
|
groups[i + 1] = (c as u16 << 8) | (d as u16);
|
|
|
|
|
return (i + 2, true);
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-20 14:17:12 -08:00
|
|
|
let group = p.read_atomically(|p| {
|
2013-08-05 21:15:55 +04:00
|
|
|
if i == 0 || p.read_given_char(':').is_some() {
|
2013-09-20 02:08:47 -04:00
|
|
|
p.read_number(16, 4, 0x10000).map(|n| n as u16)
|
2013-08-05 21:15:55 +04:00
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
2013-11-20 14:17:12 -08:00
|
|
|
});
|
2013-08-05 21:15:55 +04:00
|
|
|
match group {
|
|
|
|
|
Some(g) => groups[i] = g,
|
|
|
|
|
None => return (i, false)
|
|
|
|
|
}
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
(i, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut head = [0u16, ..8];
|
|
|
|
|
let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
|
|
|
|
|
|
|
|
|
|
if head_size == 8 {
|
|
|
|
|
return Some(Ipv6Addr(
|
|
|
|
|
head[0], head[1], head[2], head[3],
|
|
|
|
|
head[4], head[5], head[6], head[7]))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IPv4 part is not allowed before `::`
|
|
|
|
|
if head_ipv4 {
|
|
|
|
|
return None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// read `::` if previous code parsed less than 8 groups
|
|
|
|
|
if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut tail = [0u16, ..8];
|
|
|
|
|
let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
|
|
|
|
|
Some(ipv6_addr_from_head_tail(head.slice(0, head_size), tail.slice(0, tail_size)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
|
2013-11-20 14:17:12 -08:00
|
|
|
self.read_atomically(|p| p.read_ipv6_addr_impl())
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn read_ip_addr(&mut self) -> Option<IpAddr> {
|
|
|
|
|
let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr();
|
|
|
|
|
let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr();
|
|
|
|
|
self.read_or([ipv4_addr, ipv6_addr])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn read_socket_addr(&mut self) -> Option<SocketAddr> {
|
|
|
|
|
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, IpAddr, char>(open_br, ip_addr, clos_br)
|
2013-09-20 02:08:47 -04:00
|
|
|
.map(|t| match t { (_, ip, _) => ip })
|
2013-08-05 21:15:55 +04:00
|
|
|
};
|
|
|
|
|
p.read_or([ipv4_p, ipv6_p])
|
|
|
|
|
};
|
|
|
|
|
let colon = |p: &mut Parser| p.read_given_char(':');
|
2013-09-20 02:08:47 -04:00
|
|
|
let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
|
2013-08-05 21:15:55 +04:00
|
|
|
|
|
|
|
|
// host, colon, port
|
|
|
|
|
self.read_seq_3::<IpAddr, char, u16>(ip_addr, colon, port)
|
2013-09-20 02:08:47 -04:00
|
|
|
.map(|t| match t { (ip, _, port) => SocketAddr { ip: ip, port: port } })
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl FromStr for IpAddr {
|
|
|
|
|
fn from_str(s: &str) -> Option<IpAddr> {
|
2013-11-20 14:17:12 -08:00
|
|
|
Parser::new(s).read_till_eof(|p| p.read_ip_addr())
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl FromStr for SocketAddr {
|
|
|
|
|
fn from_str(s: &str) -> Option<SocketAddr> {
|
2013-11-20 14:17:12 -08:00
|
|
|
Parser::new(s).read_till_eof(|p| p.read_socket_addr())
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test {
|
2014-01-06 22:33:37 -08:00
|
|
|
use prelude::*;
|
2013-08-05 21:15:55 +04:00
|
|
|
use super::*;
|
2014-02-10 02:21:50 -08:00
|
|
|
use to_bytes::ToBytes;
|
2013-08-05 21:15:55 +04:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_from_str_ipv4() {
|
|
|
|
|
assert_eq!(Some(Ipv4Addr(127, 0, 0, 1)), FromStr::from_str("127.0.0.1"));
|
|
|
|
|
assert_eq!(Some(Ipv4Addr(255, 255, 255, 255)), FromStr::from_str("255.255.255.255"));
|
|
|
|
|
assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0"));
|
|
|
|
|
|
|
|
|
|
// out of range
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("256.0.0.1");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// too short
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("255.0.0");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// too long
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("255.0.0.1.2");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// no number between dots
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("255.0..1");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_from_str_ipv6() {
|
|
|
|
|
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("0:0:0:0:0:0:0:0"));
|
|
|
|
|
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("0:0:0:0:0:0:0:1"));
|
|
|
|
|
|
|
|
|
|
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("::1"));
|
|
|
|
|
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("::"));
|
|
|
|
|
|
|
|
|
|
assert_eq!(Some(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
|
|
|
|
|
FromStr::from_str("2a02:6b8::11:11"));
|
|
|
|
|
|
|
|
|
|
// too long group
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("::00000");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// too short
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// too long
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7:8:9");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// triple colon
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("1:2:::6:7:8");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// two double colons
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("1:2::6::8");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_from_str_ipv4_in_ipv6() {
|
|
|
|
|
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)),
|
|
|
|
|
FromStr::from_str("::192.0.2.33"));
|
|
|
|
|
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
|
|
|
|
|
FromStr::from_str("::FFFF:192.0.2.33"));
|
|
|
|
|
assert_eq!(Some(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
|
|
|
|
|
FromStr::from_str("64:ff9b::192.0.2.33"));
|
|
|
|
|
assert_eq!(Some(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
|
|
|
|
|
FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33"));
|
|
|
|
|
|
|
|
|
|
// colon after v4
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("::127.0.0.1:");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// not enought groups
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> = FromStr::from_str("1.2.3.4.5:127.0.0.1");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// too many groups
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<IpAddr> =
|
|
|
|
|
FromStr::from_str("1.2.3.4.5:6:7:127.0.0.1");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_from_str_socket_addr() {
|
|
|
|
|
assert_eq!(Some(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }),
|
|
|
|
|
FromStr::from_str("77.88.21.11:80"));
|
|
|
|
|
assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }),
|
|
|
|
|
FromStr::from_str("[2a02:6b8:0:1::1]:53"));
|
|
|
|
|
assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }),
|
|
|
|
|
FromStr::from_str("[::127.0.0.1]:22"));
|
|
|
|
|
|
|
|
|
|
// without port
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// without port
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// wrong brackets around v4
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<SocketAddr> = FromStr::from_str("[127.0.0.1]:22");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
// port out of range
|
2013-08-08 11:38:10 -07:00
|
|
|
let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:123456");
|
|
|
|
|
assert_eq!(None, none);
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|
2013-08-09 13:53:28 +04:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ipv6_addr_to_str() {
|
|
|
|
|
let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
|
|
|
|
|
assert!(a1.to_str() == ~"::ffff:192.0.2.128" || a1.to_str() == ~"::FFFF:192.0.2.128");
|
2013-11-25 07:55:58 +02:00
|
|
|
assert_eq!(Ipv6Addr(8, 9, 10, 11, 12, 13, 14, 15).to_str(), ~"8:9:a:b:c:d:e:f");
|
2013-08-09 13:53:28 +04:00
|
|
|
}
|
|
|
|
|
|
2014-02-10 02:21:50 -08:00
|
|
|
#[test]
|
|
|
|
|
fn ipv4_addr_to_bytes() {
|
|
|
|
|
Ipv4Addr(123, 20, 12, 56).to_bytes(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn socket_addr_to_bytes() {
|
|
|
|
|
SocketAddr { ip: Ipv4Addr(1, 2, 3, 4), port: 1234 }.to_bytes(true);
|
|
|
|
|
}
|
2013-08-05 21:15:55 +04:00
|
|
|
}
|