]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/net/ip.rs
doc: remove incomplete sentence
[rust.git] / src / libstd / io / net / ip.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Internet Protocol (IP) addresses.
12 //!
13 //! This module contains functions useful for parsing, formatting, and
14 //! manipulating IP addresses.
15
16 #![allow(missing_docs)]
17
18 pub use self::IpAddr::*;
19
20 use fmt;
21 use io::{mod, IoResult, IoError};
22 use io::net;
23 use iter::{Iterator, IteratorExt};
24 use ops::FnOnce;
25 use option::Option;
26 use option::Option::{None, Some};
27 use result::Result::{Ok, Err};
28 use slice::SliceExt;
29 use str::{FromStr, StrExt};
30 use vec::Vec;
31
32 pub type Port = u16;
33
34 #[deriving(Copy, PartialEq, Eq, Clone, Hash)]
35 pub enum IpAddr {
36     Ipv4Addr(u8, u8, u8, u8),
37     Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16)
38 }
39
40 impl fmt::Show for IpAddr {
41     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
42         match *self {
43             Ipv4Addr(a, b, c, d) =>
44                 write!(fmt, "{}.{}.{}.{}", a, b, c, d),
45
46             // Ipv4 Compatible address
47             Ipv6Addr(0, 0, 0, 0, 0, 0, g, h) => {
48                 write!(fmt, "::{}.{}.{}.{}", (g >> 8) as u8, g as u8,
49                        (h >> 8) as u8, h as u8)
50             }
51
52             // Ipv4-Mapped address
53             Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, g, h) => {
54                 write!(fmt, "::FFFF:{}.{}.{}.{}", (g >> 8) as u8, g as u8,
55                        (h >> 8) as u8, h as u8)
56             }
57
58             Ipv6Addr(a, b, c, d, e, f, g, h) =>
59                 write!(fmt, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
60                        a, b, c, d, e, f, g, h)
61         }
62     }
63 }
64
65 #[deriving(Copy, PartialEq, Eq, Clone, Hash)]
66 pub struct SocketAddr {
67     pub ip: IpAddr,
68     pub port: Port,
69 }
70
71 impl fmt::Show for SocketAddr {
72     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73         match self.ip {
74             Ipv4Addr(..) => write!(f, "{}:{}", self.ip, self.port),
75             Ipv6Addr(..) => write!(f, "[{}]:{}", self.ip, self.port),
76         }
77     }
78 }
79
80 struct Parser<'a> {
81     // parsing as ASCII, so can use byte array
82     s: &'a [u8],
83     pos: uint,
84 }
85
86 impl<'a> Parser<'a> {
87     fn new(s: &'a str) -> Parser<'a> {
88         Parser {
89             s: s.as_bytes(),
90             pos: 0,
91         }
92     }
93
94     fn is_eof(&self) -> bool {
95         self.pos == self.s.len()
96     }
97
98     // Commit only if parser returns Some
99     fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
100         F: FnOnce(&mut Parser) -> Option<T>,
101     {
102         let pos = self.pos;
103         let r = cb(self);
104         if r.is_none() {
105             self.pos = pos;
106         }
107         r
108     }
109
110     // Commit only if parser read till EOF
111     fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
112         F: FnOnce(&mut Parser) -> Option<T>,
113     {
114         self.read_atomically(move |p| {
115             match cb(p) {
116                 Some(x) => if p.is_eof() {Some(x)} else {None},
117                 None => None,
118             }
119         })
120     }
121
122     // Return result of first successful parser
123     fn read_or<T>(&mut self, parsers: &mut [|&mut Parser| -> Option<T>])
124                -> Option<T> {
125         for pf in parsers.iter_mut() {
126             match self.read_atomically(|p: &mut Parser| (*pf)(p)) {
127                 Some(r) => return Some(r),
128                 None => {}
129             }
130         }
131         None
132     }
133
134     // Apply 3 parsers sequentially
135     fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
136                                        pa: PA,
137                                        pb: PB,
138                                        pc: PC)
139                                        -> Option<(A, B, C)> where
140         PA: FnOnce(&mut Parser) -> Option<A>,
141         PB: FnOnce(&mut Parser) -> Option<B>,
142         PC: FnOnce(&mut Parser) -> Option<C>,
143     {
144         self.read_atomically(move |p| {
145             let a = pa(p);
146             let b = if a.is_some() { pb(p) } else { None };
147             let c = if b.is_some() { pc(p) } else { None };
148             match (a, b, c) {
149                 (Some(a), Some(b), Some(c)) => Some((a, b, c)),
150                 _ => None
151             }
152         })
153     }
154
155     // Read next char
156     fn read_char(&mut self) -> Option<char> {
157         if self.is_eof() {
158             None
159         } else {
160             let r = self.s[self.pos] as char;
161             self.pos += 1;
162             Some(r)
163         }
164     }
165
166     // Return char and advance iff next char is equal to requested
167     fn read_given_char(&mut self, c: char) -> Option<char> {
168         self.read_atomically(|p| {
169             match p.read_char() {
170                 Some(next) if next == c => Some(next),
171                 _ => None,
172             }
173         })
174     }
175
176     // Read digit
177     fn read_digit(&mut self, radix: u8) -> Option<u8> {
178         fn parse_digit(c: char, radix: u8) -> Option<u8> {
179             let c = c as u8;
180             // assuming radix is either 10 or 16
181             if c >= b'0' && c <= b'9' {
182                 Some(c - b'0')
183             } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
184                 Some(c - b'a' + 10)
185             } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
186                 Some(c - b'A' + 10)
187             } else {
188                 None
189             }
190         }
191
192         self.read_atomically(|p| {
193             p.read_char().and_then(|c| parse_digit(c, radix))
194         })
195     }
196
197     fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
198         let mut r = 0u32;
199         let mut digit_count = 0;
200         loop {
201             match self.read_digit(radix) {
202                 Some(d) => {
203                     r = r * (radix as u32) + (d as u32);
204                     digit_count += 1;
205                     if digit_count > max_digits || r >= upto {
206                         return None
207                     }
208                 }
209                 None => {
210                     if digit_count == 0 {
211                         return None
212                     } else {
213                         return Some(r)
214                     }
215                 }
216             };
217         }
218     }
219
220     // Read number, failing if max_digits of number value exceeded
221     fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
222         self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
223     }
224
225     fn read_ipv4_addr_impl(&mut self) -> Option<IpAddr> {
226         let mut bs = [0u8; 4];
227         let mut i = 0;
228         while i < 4 {
229             if i != 0 && self.read_given_char('.').is_none() {
230                 return None;
231             }
232
233             let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
234             match octet {
235                 Some(d) => bs[i] = d,
236                 None => return None,
237             };
238             i += 1;
239         }
240         Some(Ipv4Addr(bs[0], bs[1], bs[2], bs[3]))
241     }
242
243     // Read IPv4 address
244     fn read_ipv4_addr(&mut self) -> Option<IpAddr> {
245         self.read_atomically(|p| p.read_ipv4_addr_impl())
246     }
247
248     fn read_ipv6_addr_impl(&mut self) -> Option<IpAddr> {
249         fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr {
250             assert!(head.len() + tail.len() <= 8);
251             let mut gs = [0u16; 8];
252             gs.clone_from_slice(head);
253             gs.slice_mut(8 - tail.len(), 8).clone_from_slice(tail);
254             Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
255         }
256
257         fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: uint) -> (uint, bool) {
258             let mut i = 0;
259             while i < limit {
260                 if i < limit - 1 {
261                     let ipv4 = p.read_atomically(|p| {
262                         if i == 0 || p.read_given_char(':').is_some() {
263                             p.read_ipv4_addr()
264                         } else {
265                             None
266                         }
267                     });
268                     match ipv4 {
269                         Some(Ipv4Addr(a, b, c, d)) => {
270                             groups[i + 0] = ((a as u16) << 8) | (b as u16);
271                             groups[i + 1] = ((c as u16) << 8) | (d as u16);
272                             return (i + 2, true);
273                         }
274                         _ => {}
275                     }
276                 }
277
278                 let group = p.read_atomically(|p| {
279                     if i == 0 || p.read_given_char(':').is_some() {
280                         p.read_number(16, 4, 0x10000).map(|n| n as u16)
281                     } else {
282                         None
283                     }
284                 });
285                 match group {
286                     Some(g) => groups[i] = g,
287                     None => return (i, false)
288                 }
289                 i += 1;
290             }
291             (i, false)
292         }
293
294         let mut head = [0u16; 8];
295         let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
296
297         if head_size == 8 {
298             return Some(Ipv6Addr(
299                 head[0], head[1], head[2], head[3],
300                 head[4], head[5], head[6], head[7]))
301         }
302
303         // IPv4 part is not allowed before `::`
304         if head_ipv4 {
305             return None
306         }
307
308         // read `::` if previous code parsed less than 8 groups
309         if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
310             return None;
311         }
312
313         let mut tail = [0u16; 8];
314         let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
315         Some(ipv6_addr_from_head_tail(head[..head_size], tail[..tail_size]))
316     }
317
318     fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
319         self.read_atomically(|p| p.read_ipv6_addr_impl())
320     }
321
322     fn read_ip_addr(&mut self) -> Option<IpAddr> {
323         let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr();
324         let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr();
325         self.read_or(&mut [ipv4_addr, ipv6_addr])
326     }
327
328     fn read_socket_addr(&mut self) -> Option<SocketAddr> {
329         let ip_addr = |&: p: &mut Parser| {
330             let ipv4_p = |p: &mut Parser| p.read_ip_addr();
331             let ipv6_p = |p: &mut Parser| {
332                 let open_br = |&: p: &mut Parser| p.read_given_char('[');
333                 let ip_addr = |&: p: &mut Parser| p.read_ipv6_addr();
334                 let clos_br = |&: p: &mut Parser| p.read_given_char(']');
335                 p.read_seq_3::<char, IpAddr, char, _, _, _>(open_br, ip_addr, clos_br)
336                         .map(|t| match t { (_, ip, _) => ip })
337             };
338             p.read_or(&mut [ipv4_p, ipv6_p])
339         };
340         let colon = |&: p: &mut Parser| p.read_given_char(':');
341         let port  = |&: p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
342
343         // host, colon, port
344         self.read_seq_3::<IpAddr, char, u16, _, _, _>(ip_addr, colon, port)
345                 .map(|t| match t { (ip, _, port) => SocketAddr { ip: ip, port: port } })
346     }
347 }
348
349 impl FromStr for IpAddr {
350     fn from_str(s: &str) -> Option<IpAddr> {
351         Parser::new(s).read_till_eof(|p| p.read_ip_addr())
352     }
353 }
354
355 impl FromStr for SocketAddr {
356     fn from_str(s: &str) -> Option<SocketAddr> {
357         Parser::new(s).read_till_eof(|p| p.read_socket_addr())
358     }
359 }
360
361 /// A trait for objects which can be converted or resolved to one or more `SocketAddr` values.
362 ///
363 /// Implementing types minimally have to implement either `to_socket_addr` or `to_socket_addr_all`
364 /// method, and its trivial counterpart will be available automatically.
365 ///
366 /// This trait is used for generic address resolution when constructing network objects.
367 /// By default it is implemented for the following types:
368 ///
369 ///  * `SocketAddr` - `to_socket_addr` is identity function.
370 ///
371 ///  * `(IpAddr, u16)` - `to_socket_addr` constructs `SocketAddr` trivially.
372 ///
373 ///  * `(&str, u16)` - the string should be either a string representation of an IP address
374 ///    expected by `FromStr` implementation for `IpAddr` or a host name.
375 ///
376 ///    For the former, `to_socket_addr_all` returns a vector with a single element corresponding
377 ///    to that IP address joined with the given port.
378 ///
379 ///    For the latter, it tries to resolve the host name and returns a vector of all IP addresses
380 ///    for the host name, each joined with the given port.
381 ///
382 ///  * `&str` - the string should be either a string representation of a `SocketAddr` as
383 ///    expected by its `FromStr` implementation or a string like `<host_name>:<port>` pair
384 ///    where `<port>` is a `u16` value.
385 ///
386 ///    For the former, `to_socket_addr_all` returns a vector with a single element corresponding
387 ///    to that socket address.
388 ///
389 ///    For the latter, it tries to resolve the host name and returns a vector of all IP addresses
390 ///    for the host name, each joined with the port.
391 ///
392 ///
393 /// This trait allows constructing network objects like `TcpStream` or `UdpSocket` easily with
394 /// values of various types for the bind/connection address. It is needed because sometimes
395 /// one type is more appropriate than the other: for simple uses a string like `"localhost:12345"`
396 /// is much nicer than manual construction of the corresponding `SocketAddr`, but sometimes
397 /// `SocketAddr` value is *the* main source of the address, and converting it to some other type
398 /// (e.g. a string) just for it to be converted back to `SocketAddr` in constructor methods
399 /// is pointless.
400 ///
401 /// Some examples:
402 ///
403 /// ```rust,no_run
404 /// # #![allow(unused_must_use)]
405 ///
406 /// use std::io::{TcpStream, TcpListener};
407 /// use std::io::net::udp::UdpSocket;
408 /// use std::io::net::ip::{Ipv4Addr, SocketAddr};
409 ///
410 /// fn main() {
411 ///     // The following lines are equivalent modulo possible "localhost" name resolution
412 ///     // differences
413 ///     let tcp_s = TcpStream::connect(SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 12345 });
414 ///     let tcp_s = TcpStream::connect((Ipv4Addr(127, 0, 0, 1), 12345u16));
415 ///     let tcp_s = TcpStream::connect(("127.0.0.1", 12345u16));
416 ///     let tcp_s = TcpStream::connect(("localhost", 12345u16));
417 ///     let tcp_s = TcpStream::connect("127.0.0.1:12345");
418 ///     let tcp_s = TcpStream::connect("localhost:12345");
419 ///
420 ///     // TcpListener::bind(), UdpSocket::bind() and UdpSocket::send_to() behave similarly
421 ///     let tcp_l = TcpListener::bind("localhost:12345");
422 ///
423 ///     let mut udp_s = UdpSocket::bind(("127.0.0.1", 23451u16)).unwrap();
424 ///     udp_s.send_to([7u8, 7u8, 7u8].as_slice(), (Ipv4Addr(127, 0, 0, 1), 23451u16));
425 /// }
426 /// ```
427 pub trait ToSocketAddr {
428     /// Converts this object to single socket address value.
429     ///
430     /// If more than one value is available, this method returns the first one. If no
431     /// values are available, this method returns an `IoError`.
432     ///
433     /// By default this method delegates to `to_socket_addr_all` method, taking the first
434     /// item from its result.
435     fn to_socket_addr(&self) -> IoResult<SocketAddr> {
436         self.to_socket_addr_all()
437             .and_then(|v| v.into_iter().next().ok_or_else(|| IoError {
438                 kind: io::InvalidInput,
439                 desc: "no address available",
440                 detail: None
441             }))
442     }
443
444     /// Converts this object to all available socket address values.
445     ///
446     /// Some values like host name string naturally correspond to multiple IP addresses.
447     /// This method tries to return all available addresses corresponding to this object.
448     ///
449     /// By default this method delegates to `to_socket_addr` method, creating a singleton
450     /// vector from its result.
451     #[inline]
452     fn to_socket_addr_all(&self) -> IoResult<Vec<SocketAddr>> {
453         self.to_socket_addr().map(|a| vec![a])
454     }
455 }
456
457 impl ToSocketAddr for SocketAddr {
458     #[inline]
459     fn to_socket_addr(&self) -> IoResult<SocketAddr> { Ok(*self) }
460 }
461
462 impl ToSocketAddr for (IpAddr, u16) {
463     #[inline]
464     fn to_socket_addr(&self) -> IoResult<SocketAddr> {
465         let (ip, port) = *self;
466         Ok(SocketAddr { ip: ip, port: port })
467     }
468 }
469
470 fn resolve_socket_addr(s: &str, p: u16) -> IoResult<Vec<SocketAddr>> {
471     net::get_host_addresses(s)
472         .map(|v| v.into_iter().map(|a| SocketAddr { ip: a, port: p }).collect())
473 }
474
475 fn parse_and_resolve_socket_addr(s: &str) -> IoResult<Vec<SocketAddr>> {
476     macro_rules! try_opt {
477         ($e:expr, $msg:expr) => (
478             match $e {
479                 Some(r) => r,
480                 None => return Err(IoError {
481                     kind: io::InvalidInput,
482                     desc: $msg,
483                     detail: None
484                 })
485             }
486         )
487     }
488
489     // split the string by ':' and convert the second part to u16
490     let mut parts_iter = s.rsplitn(2, ':');
491     let port_str = try_opt!(parts_iter.next(), "invalid socket address");
492     let host = try_opt!(parts_iter.next(), "invalid socket address");
493     let port: u16 = try_opt!(FromStr::from_str(port_str), "invalid port value");
494     resolve_socket_addr(host, port)
495 }
496
497 impl<'a> ToSocketAddr for (&'a str, u16) {
498     fn to_socket_addr_all(&self) -> IoResult<Vec<SocketAddr>> {
499         let (host, port) = *self;
500
501         // try to parse the host as a regular IpAddr first
502         match FromStr::from_str(host) {
503             Some(addr) => return Ok(vec![SocketAddr {
504                 ip: addr,
505                 port: port
506             }]),
507             None => {}
508         }
509
510         resolve_socket_addr(host, port)
511     }
512 }
513
514 // accepts strings like 'localhost:12345'
515 impl<'a> ToSocketAddr for &'a str {
516     fn to_socket_addr(&self) -> IoResult<SocketAddr> {
517         // try to parse as a regular SocketAddr first
518         match FromStr::from_str(*self) {
519             Some(addr) => return Ok(addr),
520             None => {}
521         }
522
523         parse_and_resolve_socket_addr(*self)
524             .and_then(|v| v.into_iter().next()
525                 .ok_or_else(|| IoError {
526                     kind: io::InvalidInput,
527                     desc: "no address available",
528                     detail: None
529                 })
530             )
531     }
532
533     fn to_socket_addr_all(&self) -> IoResult<Vec<SocketAddr>> {
534         // try to parse as a regular SocketAddr first
535         match FromStr::from_str(*self) {
536             Some(addr) => return Ok(vec![addr]),
537             None => {}
538         }
539
540         parse_and_resolve_socket_addr(*self)
541     }
542 }
543
544
545 #[cfg(test)]
546 mod test {
547     use prelude::v1::*;
548     use super::*;
549     use str::FromStr;
550
551     #[test]
552     fn test_from_str_ipv4() {
553         assert_eq!(Some(Ipv4Addr(127, 0, 0, 1)), FromStr::from_str("127.0.0.1"));
554         assert_eq!(Some(Ipv4Addr(255, 255, 255, 255)), FromStr::from_str("255.255.255.255"));
555         assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0"));
556
557         // out of range
558         let none: Option<IpAddr> = FromStr::from_str("256.0.0.1");
559         assert_eq!(None, none);
560         // too short
561         let none: Option<IpAddr> = FromStr::from_str("255.0.0");
562         assert_eq!(None, none);
563         // too long
564         let none: Option<IpAddr> = FromStr::from_str("255.0.0.1.2");
565         assert_eq!(None, none);
566         // no number between dots
567         let none: Option<IpAddr> = FromStr::from_str("255.0..1");
568         assert_eq!(None, none);
569     }
570
571     #[test]
572     fn test_from_str_ipv6() {
573         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("0:0:0:0:0:0:0:0"));
574         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("0:0:0:0:0:0:0:1"));
575
576         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("::1"));
577         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("::"));
578
579         assert_eq!(Some(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
580                 FromStr::from_str("2a02:6b8::11:11"));
581
582         // too long group
583         let none: Option<IpAddr> = FromStr::from_str("::00000");
584         assert_eq!(None, none);
585         // too short
586         let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7");
587         assert_eq!(None, none);
588         // too long
589         let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7:8:9");
590         assert_eq!(None, none);
591         // triple colon
592         let none: Option<IpAddr> = FromStr::from_str("1:2:::6:7:8");
593         assert_eq!(None, none);
594         // two double colons
595         let none: Option<IpAddr> = FromStr::from_str("1:2::6::8");
596         assert_eq!(None, none);
597     }
598
599     #[test]
600     fn test_from_str_ipv4_in_ipv6() {
601         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)),
602                 FromStr::from_str("::192.0.2.33"));
603         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
604                 FromStr::from_str("::FFFF:192.0.2.33"));
605         assert_eq!(Some(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
606                 FromStr::from_str("64:ff9b::192.0.2.33"));
607         assert_eq!(Some(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
608                 FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33"));
609
610         // colon after v4
611         let none: Option<IpAddr> = FromStr::from_str("::127.0.0.1:");
612         assert_eq!(None, none);
613         // not enough groups
614         let none: Option<IpAddr> = FromStr::from_str("1.2.3.4.5:127.0.0.1");
615         assert_eq!(None, none);
616         // too many groups
617         let none: Option<IpAddr> =
618             FromStr::from_str("1.2.3.4.5:6:7:127.0.0.1");
619         assert_eq!(None, none);
620     }
621
622     #[test]
623     fn test_from_str_socket_addr() {
624         assert_eq!(Some(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }),
625                 FromStr::from_str("77.88.21.11:80"));
626         assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }),
627                 FromStr::from_str("[2a02:6b8:0:1::1]:53"));
628         assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }),
629                 FromStr::from_str("[::127.0.0.1]:22"));
630
631         // without port
632         let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1");
633         assert_eq!(None, none);
634         // without port
635         let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:");
636         assert_eq!(None, none);
637         // wrong brackets around v4
638         let none: Option<SocketAddr> = FromStr::from_str("[127.0.0.1]:22");
639         assert_eq!(None, none);
640         // port out of range
641         let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:123456");
642         assert_eq!(None, none);
643     }
644
645     #[test]
646     fn ipv6_addr_to_string() {
647         let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
648         assert!(a1.to_string() == "::ffff:192.0.2.128" ||
649                 a1.to_string() == "::FFFF:192.0.2.128");
650         assert_eq!(Ipv6Addr(8, 9, 10, 11, 12, 13, 14, 15).to_string(),
651                    "8:9:a:b:c:d:e:f");
652     }
653
654     #[test]
655     fn to_socket_addr_socketaddr() {
656         let a = SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 12345 };
657         assert_eq!(Ok(a), a.to_socket_addr());
658         assert_eq!(Ok(vec![a]), a.to_socket_addr_all());
659     }
660
661     #[test]
662     fn to_socket_addr_ipaddr_u16() {
663         let a = Ipv4Addr(77, 88, 21, 11);
664         let p = 12345u16;
665         let e = SocketAddr { ip: a, port: p };
666         assert_eq!(Ok(e), (a, p).to_socket_addr());
667         assert_eq!(Ok(vec![e]), (a, p).to_socket_addr_all());
668     }
669
670     #[test]
671     fn to_socket_addr_str_u16() {
672         let a = SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 24352 };
673         assert_eq!(Ok(a), ("77.88.21.11", 24352u16).to_socket_addr());
674         assert_eq!(Ok(vec![a]), ("77.88.21.11", 24352u16).to_socket_addr_all());
675
676         let a = SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 };
677         assert_eq!(Ok(a), ("2a02:6b8:0:1::1", 53).to_socket_addr());
678         assert_eq!(Ok(vec![a]), ("2a02:6b8:0:1::1", 53).to_socket_addr_all());
679
680         let a = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 23924 };
681         assert!(("localhost", 23924u16).to_socket_addr_all().unwrap().contains(&a));
682     }
683
684     #[test]
685     fn to_socket_addr_str() {
686         let a = SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 24352 };
687         assert_eq!(Ok(a), "77.88.21.11:24352".to_socket_addr());
688         assert_eq!(Ok(vec![a]), "77.88.21.11:24352".to_socket_addr_all());
689
690         let a = SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 };
691         assert_eq!(Ok(a), "[2a02:6b8:0:1::1]:53".to_socket_addr());
692         assert_eq!(Ok(vec![a]), "[2a02:6b8:0:1::1]:53".to_socket_addr_all());
693
694         let a = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 23924 };
695         assert!("localhost:23924".to_socket_addr_all().unwrap().contains(&a));
696     }
697 }