1 use crate::cmp::Ordering;
2 use crate::fmt::{self, Write as FmtWrite};
3 use crate::hash;
4 use crate::io::Write as IoWrite;
5 use crate::mem::transmute;
6 use crate::sys::net::netc as c;
7 use crate::sys_common::{AsInner, FromInner, IntoInner};
8 #[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
9 pub enum IpAddr {
10     V4(Ipv4Addr),
11     V6(Ipv6Addr),
12 }
13 #[derive(Copy)]
14 pub struct Ipv4Addr {
15     inner: c::in_addr,
16 }
17 #[derive(Copy)]
18 pub struct Ipv6Addr {
19     inner: c::in6_addr,
20 }
21 #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
22 #[non_exhaustive]
23 pub enum Ipv6MulticastScope {
24     InterfaceLocal,
25     LinkLocal,
26     RealmLocal,
27     AdminLocal,
28     SiteLocal,
29     OrganizationLocal,
30     Global,
31 }
32 impl IpAddr {
is_unspecified(&self) -> bool33     pub const fn is_unspecified(&self) -> bool {
34         match self {
35             IpAddr::V4(ip) => ip.is_unspecified(),
36             IpAddr::V6(ip) => ip.is_unspecified(),
37         }
38     }
is_loopback(&self) -> bool39     pub const fn is_loopback(&self) -> bool {
40         match self {
41             IpAddr::V4(ip) => ip.is_loopback(),
42             IpAddr::V6(ip) => ip.is_loopback(),
43         }
44     }
is_global(&self) -> bool45     pub const fn is_global(&self) -> bool {
46         match self {
47             IpAddr::V4(ip) => ip.is_global(),
48             IpAddr::V6(ip) => ip.is_global(),
49         }
50     }
is_multicast(&self) -> bool51     pub const fn is_multicast(&self) -> bool {
52         match self {
53             IpAddr::V4(ip) => ip.is_multicast(),
54             IpAddr::V6(ip) => ip.is_multicast(),
55         }
56     }
is_documentation(&self) -> bool57     pub const fn is_documentation(&self) -> bool {
58         match self {
59             IpAddr::V4(ip) => ip.is_documentation(),
60             IpAddr::V6(ip) => ip.is_documentation(),
61         }
62     }
is_benchmarking(&self) -> bool63     pub const fn is_benchmarking(&self) -> bool {
64         match self {
65             IpAddr::V4(ip) => ip.is_benchmarking(),
66             IpAddr::V6(ip) => ip.is_benchmarking(),
67         }
68     }
is_ipv4(&self) -> bool69     pub const fn is_ipv4(&self) -> bool {
70         matches!(self, IpAddr::V4(_))
71     }
is_ipv6(&self) -> bool72     pub const fn is_ipv6(&self) -> bool {
73         matches!(self, IpAddr::V6(_))
74     }
to_canonical(&self) -> IpAddr75     pub const fn to_canonical(&self) -> IpAddr {
76         match self {
77             &v4 @ IpAddr::V4(_) => v4,
78             IpAddr::V6(v6) => v6.to_canonical(),
79         }
80     }
81 }
82 impl Ipv4Addr {
new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr83     pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
84         Ipv4Addr {
85             inner: c::in_addr {
86                 s_addr: u32::from_ne_bytes([a, b, c, d]),
87             },
88         }
89     }
90     pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
91     #[doc(alias = "INADDR_ANY")]
92     pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
93     pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
octets(&self) -> [u8; 4]94     pub const fn octets(&self) -> [u8; 4] {
95         self.inner.s_addr.to_ne_bytes()
96     }
is_unspecified(&self) -> bool97     pub const fn is_unspecified(&self) -> bool {
98         self.inner.s_addr == 0
99     }
is_loopback(&self) -> bool100     pub const fn is_loopback(&self) -> bool {
101         self.octets()[0] == 127
102     }
is_private(&self) -> bool103     pub const fn is_private(&self) -> bool {
104         match self.octets() {
105             [10, ..] => true,
106             [172, b, ..] if b >= 16 && b <= 31 => true,
107             [192, 168, ..] => true,
108             _ => false,
109         }
110     }
is_link_local(&self) -> bool111     pub const fn is_link_local(&self) -> bool {
112         matches!(self.octets(), [169, 254, ..])
113     }
is_global(&self) -> bool114     pub const fn is_global(&self) -> bool {
115         if u32::from_be_bytes(self.octets()) == 0xc0000009
116             || u32::from_be_bytes(self.octets()) == 0xc000000a
117         {
118             return true;
119         }
120         !self.is_private() && !self.is_loopback() && !self.is_link_local()
121             && !self.is_broadcast() && !self.is_documentation() && !self.is_shared()
122             && !(self.octets()[0] == 192 && self.octets()[1] == 0
123                 && self.octets()[2] == 0) && !self.is_reserved()
124             && !self.is_benchmarking() && self.octets()[0] != 0
125     }
is_shared(&self) -> bool126     pub const fn is_shared(&self) -> bool {
127         self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
128     }
is_benchmarking(&self) -> bool129     pub const fn is_benchmarking(&self) -> bool {
130         self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
131     }
is_reserved(&self) -> bool132     pub const fn is_reserved(&self) -> bool {
133         self.octets()[0] & 240 == 240 && !self.is_broadcast()
134     }
is_multicast(&self) -> bool135     pub const fn is_multicast(&self) -> bool {
136         self.octets()[0] >= 224 && self.octets()[0] <= 239
137     }
is_broadcast(&self) -> bool138     pub const fn is_broadcast(&self) -> bool {
139         u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
140     }
is_documentation(&self) -> bool141     pub const fn is_documentation(&self) -> bool {
142         matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
143     }
to_ipv6_compatible(&self) -> Ipv6Addr144     pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
145         let [a, b, c, d] = self.octets();
146         Ipv6Addr {
147             inner: c::in6_addr {
148                 s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d],
149             },
150         }
151     }
to_ipv6_mapped(&self) -> Ipv6Addr152     pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
153         let [a, b, c, d] = self.octets();
154         Ipv6Addr {
155             inner: c::in6_addr {
156                 s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d],
157             },
158         }
159     }
160 }
161 impl fmt::Display for IpAddr {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result162     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
163         match self {
164             IpAddr::V4(ip) => ip.fmt(fmt),
165             IpAddr::V6(ip) => ip.fmt(fmt),
166         }
167     }
168 }
169 impl fmt::Debug for IpAddr {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result170     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
171         fmt::Display::fmt(self, fmt)
172     }
173 }
174 impl From<Ipv4Addr> for IpAddr {
from(ipv4: Ipv4Addr) -> IpAddr175     fn from(ipv4: Ipv4Addr) -> IpAddr {
176         IpAddr::V4(ipv4)
177     }
178 }
179 impl From<Ipv6Addr> for IpAddr {
from(ipv6: Ipv6Addr) -> IpAddr180     fn from(ipv6: Ipv6Addr) -> IpAddr {
181         IpAddr::V6(ipv6)
182     }
183 }
184 impl fmt::Display for Ipv4Addr {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result185     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
186         let octets = self.octets();
187         if fmt.precision().is_none() && fmt.width().is_none() {
188             write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
189         } else {
190             const IPV4_BUF_LEN: usize = 15;
191             let mut buf = [0u8; IPV4_BUF_LEN];
192             let mut buf_slice = &mut buf[..];
193             write!(buf_slice, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
194                 .unwrap();
195             let len = IPV4_BUF_LEN - buf_slice.len();
196             let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
197             fmt.pad(buf)
198         }
199     }
200 }
201 impl fmt::Debug for Ipv4Addr {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result202     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
203         fmt::Display::fmt(self, fmt)
204     }
205 }
206 impl Clone for Ipv4Addr {
clone(&self) -> Ipv4Addr207     fn clone(&self) -> Ipv4Addr {
208         *self
209     }
210 }
211 impl PartialEq for Ipv4Addr {
eq(&self, other: &Ipv4Addr) -> bool212     fn eq(&self, other: &Ipv4Addr) -> bool {
213         self.inner.s_addr == other.inner.s_addr
214     }
215 }
216 impl PartialEq<Ipv4Addr> for IpAddr {
eq(&self, other: &Ipv4Addr) -> bool217     fn eq(&self, other: &Ipv4Addr) -> bool {
218         match self {
219             IpAddr::V4(v4) => v4 == other,
220             IpAddr::V6(_) => false,
221         }
222     }
223 }
224 impl PartialEq<IpAddr> for Ipv4Addr {
eq(&self, other: &IpAddr) -> bool225     fn eq(&self, other: &IpAddr) -> bool {
226         match other {
227             IpAddr::V4(v4) => self == v4,
228             IpAddr::V6(_) => false,
229         }
230     }
231 }
232 impl Eq for Ipv4Addr {}
233 impl hash::Hash for Ipv4Addr {
hash<H: hash::Hasher>(&self, s: &mut H)234     fn hash<H: hash::Hasher>(&self, s: &mut H) {
235         { self.inner.s_addr }.hash(s)
236     }
237 }
238 impl PartialOrd for Ipv4Addr {
partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering>239     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
240         Some(self.cmp(other))
241     }
242 }
243 impl PartialOrd<Ipv4Addr> for IpAddr {
partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering>244     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
245         match self {
246             IpAddr::V4(v4) => v4.partial_cmp(other),
247             IpAddr::V6(_) => Some(Ordering::Greater),
248         }
249     }
250 }
251 impl PartialOrd<IpAddr> for Ipv4Addr {
partial_cmp(&self, other: &IpAddr) -> Option<Ordering>252     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
253         match other {
254             IpAddr::V4(v4) => self.partial_cmp(v4),
255             IpAddr::V6(_) => Some(Ordering::Less),
256         }
257     }
258 }
259 impl Ord for Ipv4Addr {
cmp(&self, other: &Ipv4Addr) -> Ordering260     fn cmp(&self, other: &Ipv4Addr) -> Ordering {
261         u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
262     }
263 }
264 impl IntoInner<c::in_addr> for Ipv4Addr {
into_inner(self) -> c::in_addr265     fn into_inner(self) -> c::in_addr {
266         self.inner
267     }
268 }
269 impl From<Ipv4Addr> for u32 {
from(ip: Ipv4Addr) -> u32270     fn from(ip: Ipv4Addr) -> u32 {
271         let ip = ip.octets();
272         u32::from_be_bytes(ip)
273     }
274 }
275 impl From<u32> for Ipv4Addr {
from(ip: u32) -> Ipv4Addr276     fn from(ip: u32) -> Ipv4Addr {
277         Ipv4Addr::from(ip.to_be_bytes())
278     }
279 }
280 impl From<[u8; 4]> for Ipv4Addr {
from(octets: [u8; 4]) -> Ipv4Addr281     fn from(octets: [u8; 4]) -> Ipv4Addr {
282         Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
283     }
284 }
285 impl From<[u8; 4]> for IpAddr {
from(octets: [u8; 4]) -> IpAddr286     fn from(octets: [u8; 4]) -> IpAddr {
287         IpAddr::V4(Ipv4Addr::from(octets))
288     }
289 }
290 impl Ipv6Addr {
new( a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16, ) -> Ipv6Addr291     pub const fn new(
292         a: u16,
293         b: u16,
294         c: u16,
295         d: u16,
296         e: u16,
297         f: u16,
298         g: u16,
299         h: u16,
300     ) -> Ipv6Addr {
301         let addr16 = [
302             a.to_be(),
303             b.to_be(),
304             c.to_be(),
305             d.to_be(),
306             e.to_be(),
307             f.to_be(),
308             g.to_be(),
309             h.to_be(),
310         ];
311         Ipv6Addr {
312             inner: c::in6_addr {
313                 s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
314             },
315         }
316     }
317     pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
318     pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
segments(&self) -> [u16; 8]319     pub const fn segments(&self) -> [u16; 8] {
320         let [a, b, c, d, e, f, g, h] = unsafe {
321             transmute::<_, [u16; 8]>(self.inner.s6_addr)
322         };
323         [
324             u16::from_be(a),
325             u16::from_be(b),
326             u16::from_be(c),
327             u16::from_be(d),
328             u16::from_be(e),
329             u16::from_be(f),
330             u16::from_be(g),
331             u16::from_be(h),
332         ]
333     }
is_unspecified(&self) -> bool334     pub const fn is_unspecified(&self) -> bool {
335         u128::from_be_bytes(self.octets())
336             == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
337     }
is_loopback(&self) -> bool338     pub const fn is_loopback(&self) -> bool {
339         u128::from_be_bytes(self.octets())
340             == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
341     }
is_global(&self) -> bool342     pub const fn is_global(&self) -> bool {
343         match self.multicast_scope() {
344             Some(Ipv6MulticastScope::Global) => true,
345             None => self.is_unicast_global(),
346             _ => false,
347         }
348     }
is_unique_local(&self) -> bool349     pub const fn is_unique_local(&self) -> bool {
350         (self.segments()[0] & 0xfe00) == 0xfc00
351     }
is_unicast(&self) -> bool352     pub const fn is_unicast(&self) -> bool {
353         !self.is_multicast()
354     }
is_unicast_link_local(&self) -> bool355     pub const fn is_unicast_link_local(&self) -> bool {
356         (self.segments()[0] & 0xffc0) == 0xfe80
357     }
is_documentation(&self) -> bool358     pub const fn is_documentation(&self) -> bool {
359         (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
360     }
is_benchmarking(&self) -> bool361     pub const fn is_benchmarking(&self) -> bool {
362         (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2)
363             && (self.segments()[2] == 0)
364     }
is_unicast_global(&self) -> bool365     pub const fn is_unicast_global(&self) -> bool {
366         self.is_unicast() && !self.is_loopback() && !self.is_unicast_link_local()
367             && !self.is_unique_local() && !self.is_unspecified()
368             && !self.is_documentation()
369     }
multicast_scope(&self) -> Option<Ipv6MulticastScope>370     pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
371         if self.is_multicast() {
372             match self.segments()[0] & 0x000f {
373                 1 => Some(Ipv6MulticastScope::InterfaceLocal),
374                 2 => Some(Ipv6MulticastScope::LinkLocal),
375                 3 => Some(Ipv6MulticastScope::RealmLocal),
376                 4 => Some(Ipv6MulticastScope::AdminLocal),
377                 5 => Some(Ipv6MulticastScope::SiteLocal),
378                 8 => Some(Ipv6MulticastScope::OrganizationLocal),
379                 14 => Some(Ipv6MulticastScope::Global),
380                 _ => None,
381             }
382         } else {
383             None
384         }
385     }
is_multicast(&self) -> bool386     pub const fn is_multicast(&self) -> bool {
387         (self.segments()[0] & 0xff00) == 0xff00
388     }
to_ipv4_mapped(&self) -> Option<Ipv4Addr>389     pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
390         match self.octets() {
391             [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
392                 Some(Ipv4Addr::new(a, b, c, d))
393             }
394             _ => None,
395         }
396     }
to_ipv4(&self) -> Option<Ipv4Addr>397     pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
398         if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
399             let [a, b] = ab.to_be_bytes();
400             let [c, d] = cd.to_be_bytes();
401             Some(Ipv4Addr::new(a, b, c, d))
402         } else {
403             None
404         }
405     }
to_canonical(&self) -> IpAddr406     pub const fn to_canonical(&self) -> IpAddr {
407         if let Some(mapped) = self.to_ipv4_mapped() {
408             return IpAddr::V4(mapped);
409         }
410         IpAddr::V6(*self)
411     }
octets(&self) -> [u8; 16]412     pub const fn octets(&self) -> [u8; 16] {
413         self.inner.s6_addr
414     }
415 }
416 impl fmt::Display for Ipv6Addr {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result417     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
418         if f.precision().is_none() && f.width().is_none() {
419             let segments = self.segments();
420             if self.is_unspecified() {
421                 f.write_str("::")
422             } else if self.is_loopback() {
423                 f.write_str("::1")
424             } else if let Some(ipv4) = self.to_ipv4() {
425                 match segments[5] {
426                     0 => write!(f, "::{}", ipv4),
427                     0xffff => write!(f, "::ffff:{}", ipv4),
428                     _ => unreachable!(),
429                 }
430             } else {
431                 #[derive(Copy, Clone, Default)]
432                 struct Span {
433                     start: usize,
434                     len: usize,
435                 }
436                 let zeroes = {
437                     let mut longest = Span::default();
438                     let mut current = Span::default();
439                     for (i, &segment) in segments.iter().enumerate() {
440                         if segment == 0 {
441                             if current.len == 0 {
442                                 current.start = i;
443                             }
444                             current.len += 1;
445                             if current.len > longest.len {
446                                 longest = current;
447                             }
448                         } else {
449                             current = Span::default();
450                         }
451                     }
452                     longest
453                 };
454                 /// Write a colon-separated part of the address
455                 #[inline]
456                 fn fmt_subslice(
457                     f: &mut fmt::Formatter<'_>,
458                     chunk: &[u16],
459                 ) -> fmt::Result {
460                     if let Some((first, tail)) = chunk.split_first() {
461                         write!(f, "{:x}", first)?;
462                         for segment in tail {
463                             f.write_char(':')?;
464                             write!(f, "{:x}", segment)?;
465                         }
466                     }
467                     Ok(())
468                 }
469                 if zeroes.len > 1 {
470                     fmt_subslice(f, &segments[..zeroes.start])?;
471                     f.write_str("::")?;
472                     fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
473                 } else {
474                     fmt_subslice(f, &segments)
475                 }
476             }
477         } else {
478             const IPV6_BUF_LEN: usize = (4 * 8) + 7;
479             let mut buf = [0u8; IPV6_BUF_LEN];
480             let mut buf_slice = &mut buf[..];
481             write!(buf_slice, "{}", self).unwrap();
482             let len = IPV6_BUF_LEN - buf_slice.len();
483             let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
484             f.pad(buf)
485         }
486     }
487 }
488 impl fmt::Debug for Ipv6Addr {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result489     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
490         fmt::Display::fmt(self, fmt)
491     }
492 }
493 impl Clone for Ipv6Addr {
clone(&self) -> Ipv6Addr494     fn clone(&self) -> Ipv6Addr {
495         *self
496     }
497 }
498 impl PartialEq for Ipv6Addr {
eq(&self, other: &Ipv6Addr) -> bool499     fn eq(&self, other: &Ipv6Addr) -> bool {
500         self.inner.s6_addr == other.inner.s6_addr
501     }
502 }
503 impl PartialEq<IpAddr> for Ipv6Addr {
eq(&self, other: &IpAddr) -> bool504     fn eq(&self, other: &IpAddr) -> bool {
505         match other {
506             IpAddr::V4(_) => false,
507             IpAddr::V6(v6) => self == v6,
508         }
509     }
510 }
511 impl PartialEq<Ipv6Addr> for IpAddr {
eq(&self, other: &Ipv6Addr) -> bool512     fn eq(&self, other: &Ipv6Addr) -> bool {
513         match self {
514             IpAddr::V4(_) => false,
515             IpAddr::V6(v6) => v6 == other,
516         }
517     }
518 }
519 impl Eq for Ipv6Addr {}
520 impl hash::Hash for Ipv6Addr {
hash<H: hash::Hasher>(&self, s: &mut H)521     fn hash<H: hash::Hasher>(&self, s: &mut H) {
522         self.inner.s6_addr.hash(s)
523     }
524 }
525 impl PartialOrd for Ipv6Addr {
partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering>526     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
527         Some(self.cmp(other))
528     }
529 }
530 impl PartialOrd<Ipv6Addr> for IpAddr {
partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering>531     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
532         match self {
533             IpAddr::V4(_) => Some(Ordering::Less),
534             IpAddr::V6(v6) => v6.partial_cmp(other),
535         }
536     }
537 }
538 impl PartialOrd<IpAddr> for Ipv6Addr {
partial_cmp(&self, other: &IpAddr) -> Option<Ordering>539     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
540         match other {
541             IpAddr::V4(_) => Some(Ordering::Greater),
542             IpAddr::V6(v6) => self.partial_cmp(v6),
543         }
544     }
545 }
546 impl Ord for Ipv6Addr {
cmp(&self, other: &Ipv6Addr) -> Ordering547     fn cmp(&self, other: &Ipv6Addr) -> Ordering {
548         self.segments().cmp(&other.segments())
549     }
550 }
551 impl AsInner<c::in6_addr> for Ipv6Addr {
as_inner(&self) -> &c::in6_addr552     fn as_inner(&self) -> &c::in6_addr {
553         &self.inner
554     }
555 }
556 impl FromInner<c::in6_addr> for Ipv6Addr {
from_inner(addr: c::in6_addr) -> Ipv6Addr557     fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
558         Ipv6Addr { inner: addr }
559     }
560 }
561 impl From<Ipv6Addr> for u128 {
from(ip: Ipv6Addr) -> u128562     fn from(ip: Ipv6Addr) -> u128 {
563         let ip = ip.octets();
564         u128::from_be_bytes(ip)
565     }
566 }
567 impl From<u128> for Ipv6Addr {
from(ip: u128) -> Ipv6Addr568     fn from(ip: u128) -> Ipv6Addr {
569         Ipv6Addr::from(ip.to_be_bytes())
570     }
571 }
572 impl From<[u8; 16]> for Ipv6Addr {
from(octets: [u8; 16]) -> Ipv6Addr573     fn from(octets: [u8; 16]) -> Ipv6Addr {
574         let inner = c::in6_addr { s6_addr: octets };
575         Ipv6Addr::from_inner(inner)
576     }
577 }
578 impl From<[u16; 8]> for Ipv6Addr {
from(segments: [u16; 8]) -> Ipv6Addr579     fn from(segments: [u16; 8]) -> Ipv6Addr {
580         let [a, b, c, d, e, f, g, h] = segments;
581         Ipv6Addr::new(a, b, c, d, e, f, g, h)
582     }
583 }
584 impl From<[u8; 16]> for IpAddr {
from(octets: [u8; 16]) -> IpAddr585     fn from(octets: [u8; 16]) -> IpAddr {
586         IpAddr::V6(Ipv6Addr::from(octets))
587     }
588 }
589 impl From<[u16; 8]> for IpAddr {
from(segments: [u16; 8]) -> IpAddr590     fn from(segments: [u16; 8]) -> IpAddr {
591         IpAddr::V6(Ipv6Addr::from(segments))
592     }
593 }
594