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