1 use crate::cmp::Ordering;use crate::fmt::{self, Write as FmtWrite}; 2 use crate::hash; 3 use crate::io::Write as IoWrite; 4 use crate::mem::transmute; 5 use crate::sys::net::netc as c; 6 use crate::sys_common::{AsInner, FromInner, IntoInner}; 7 #[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] 8 pub enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), } 9 #[derive(Copy)] 10 pub struct Ipv4Addr { 11 inner: c::in_addr, 12 } 13 #[derive(Copy)] 14 pub struct Ipv6Addr { 15 inner: c::in6_addr, 16 } 17 #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)] 18 #[non_exhaustive] 19 pub enum Ipv6MulticastScope { 20 InterfaceLocal, 21 LinkLocal, 22 RealmLocal, 23 AdminLocal, 24 SiteLocal, 25 OrganizationLocal, 26 Global, 27 } 28 impl IpAddr { is_unspecified(&self) -> bool29 pub const fn is_unspecified(&self) -> bool { 30 match self { 31 IpAddr::V4(ip) => ip.is_unspecified(), 32 IpAddr::V6(ip) => ip.is_unspecified(), 33 } 34 } is_loopback(&self) -> bool35 pub const fn is_loopback(&self) -> bool { 36 match self { 37 IpAddr::V4(ip) => ip.is_loopback(), 38 IpAddr::V6(ip) => ip.is_loopback(), 39 } 40 } is_global(&self) -> bool41 pub const fn is_global(&self) -> bool { 42 match self { 43 IpAddr::V4(ip) => ip.is_global(), 44 IpAddr::V6(ip) => ip.is_global(), 45 } 46 } is_multicast(&self) -> bool47 pub const fn is_multicast(&self) -> bool { 48 match self { 49 IpAddr::V4(ip) => ip.is_multicast(), 50 IpAddr::V6(ip) => ip.is_multicast(), 51 } 52 } is_documentation(&self) -> bool53 pub const fn is_documentation(&self) -> bool { 54 match self { 55 IpAddr::V4(ip) => ip.is_documentation(), 56 IpAddr::V6(ip) => ip.is_documentation(), 57 } 58 } is_benchmarking(&self) -> bool59 pub const fn is_benchmarking(&self) -> bool { 60 match self { 61 IpAddr::V4(ip) => ip.is_benchmarking(), 62 IpAddr::V6(ip) => ip.is_benchmarking(), 63 } 64 } is_ipv4(&self) -> bool65 pub const fn is_ipv4(&self) -> bool { matches!(self, IpAddr :: V4(_)) } is_ipv6(&self) -> bool66 pub const fn is_ipv6(&self) -> bool { matches!(self, IpAddr :: V6(_)) } to_canonical(&self) -> IpAddr67 pub const fn to_canonical(&self) -> IpAddr { 68 match self { 69 &v4 @ IpAddr::V4(_) => v4, 70 IpAddr::V6(v6) => v6.to_canonical(), 71 } 72 } 73 } 74 impl Ipv4Addr { new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr75 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { 76 Ipv4Addr { 77 inner: c::in_addr { s_addr: u32::from_ne_bytes([a, b, c, d]) }, 78 } 79 } 80 pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1); 81 #[doc(alias = "INADDR_ANY")] 82 pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0); 83 pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255); octets(&self) -> [u8; 4]84 pub const fn octets(&self) -> [u8; 4] { self.inner.s_addr.to_ne_bytes() } is_unspecified(&self) -> bool85 pub const fn is_unspecified(&self) -> bool { self.inner.s_addr == 0 } is_loopback(&self) -> bool86 pub const fn is_loopback(&self) -> bool { self.octets()[0] == 127 } is_private(&self) -> bool87 pub const fn is_private(&self) -> bool { 88 match self.octets() { 89 [10, ..] => true, 90 [172, b, ..] if b >= 16 && b <= 31 => true, 91 [192, 168, ..] => true, 92 _ => false, 93 } 94 } is_link_local(&self) -> bool95 pub const fn is_link_local(&self) -> bool { 96 matches!(self.octets(), [169, 254, ..]) 97 } is_global(&self) -> bool98 pub const fn is_global(&self) -> bool { 99 if u32::from_be_bytes(self.octets()) == 0xc0000009 || 100 u32::from_be_bytes(self.octets()) == 0xc000000a { 101 return true; 102 } 103 !self.is_private() && !self.is_loopback() && !self.is_link_local() && 104 !self.is_broadcast() && !self.is_documentation() && 105 !self.is_shared() && 106 !(self.octets()[0] == 192 && self.octets()[1] == 0 && 107 self.octets()[2] == 0) && !self.is_reserved() && 108 !self.is_benchmarking() && self.octets()[0] != 0 109 } is_shared(&self) -> bool110 pub const fn is_shared(&self) -> bool { 111 self.octets()[0] == 100 && 112 (self.octets()[1] & 0b1100_0000 == 0b0100_0000) 113 } is_benchmarking(&self) -> bool114 pub const fn is_benchmarking(&self) -> bool { 115 self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 116 } is_reserved(&self) -> bool117 pub const fn is_reserved(&self) -> bool { 118 self.octets()[0] & 240 == 240 && !self.is_broadcast() 119 } is_multicast(&self) -> bool120 pub const fn is_multicast(&self) -> bool { 121 self.octets()[0] >= 224 && self.octets()[0] <= 239 122 } is_broadcast(&self) -> bool123 pub const fn is_broadcast(&self) -> bool { 124 u32::from_be_bytes(self.octets()) == 125 u32::from_be_bytes(Self::BROADCAST.octets()) 126 } is_documentation(&self) -> bool127 pub const fn is_documentation(&self) -> bool { 128 matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | 129 [203, 0, 113, _]) 130 } to_ipv6_compatible(&self) -> Ipv6Addr131 pub const fn to_ipv6_compatible(&self) -> Ipv6Addr { 132 let [a, b, c, d] = self.octets(); 133 Ipv6Addr { 134 inner: c::in6_addr { 135 s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d], 136 }, 137 } 138 } to_ipv6_mapped(&self) -> Ipv6Addr139 pub const fn to_ipv6_mapped(&self) -> Ipv6Addr { 140 let [a, b, c, d] = self.octets(); 141 Ipv6Addr { 142 inner: c::in6_addr { 143 s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, 144 d], 145 }, 146 } 147 } 148 } 149 impl fmt::Display for IpAddr { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result150 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 151 match self { 152 IpAddr::V4(ip) => ip.fmt(fmt), 153 IpAddr::V6(ip) => ip.fmt(fmt), 154 } 155 } 156 } 157 impl fmt::Debug for IpAddr { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result158 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 159 fmt::Display::fmt(self, fmt) 160 } 161 } 162 impl From<Ipv4Addr> for IpAddr { from(ipv4: Ipv4Addr) -> IpAddr163 fn from(ipv4: Ipv4Addr) -> IpAddr { IpAddr::V4(ipv4) } 164 } 165 impl From<Ipv6Addr> for IpAddr { from(ipv6: Ipv6Addr) -> IpAddr166 fn from(ipv6: Ipv6Addr) -> IpAddr { IpAddr::V6(ipv6) } 167 } 168 impl fmt::Display for Ipv4Addr { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result169 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 170 let octets = self.octets(); 171 if fmt.precision().is_none() && fmt.width().is_none() { 172 write!(fmt, "{}.{}.{}.{}", octets [0], octets [1], octets [2], 173 octets [3]) 174 } else { 175 const IPV4_BUF_LEN: usize = 15; 176 let mut buf = [0u8; IPV4_BUF_LEN]; 177 let mut buf_slice = &mut buf[..]; 178 write!(buf_slice, "{}.{}.{}.{}", octets [0], octets [1], octets 179 [2], octets [3]).unwrap(); 180 let len = IPV4_BUF_LEN - buf_slice.len(); 181 let buf = 182 unsafe { crate::str::from_utf8_unchecked(&buf[..len]) }; 183 fmt.pad(buf) 184 } 185 } 186 } 187 impl fmt::Debug for Ipv4Addr { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result188 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 189 fmt::Display::fmt(self, fmt) 190 } 191 } 192 impl Clone for Ipv4Addr { clone(&self) -> Ipv4Addr193 fn clone(&self) -> Ipv4Addr { *self } 194 } 195 impl PartialEq for Ipv4Addr { eq(&self, other: &Ipv4Addr) -> bool196 fn eq(&self, other: &Ipv4Addr) -> bool { 197 self.inner.s_addr == other.inner.s_addr 198 } 199 } 200 impl PartialEq<Ipv4Addr> for IpAddr { eq(&self, other: &Ipv4Addr) -> bool201 fn eq(&self, other: &Ipv4Addr) -> bool { 202 match self { IpAddr::V4(v4) => v4 == other, IpAddr::V6(_) => false, } 203 } 204 } 205 impl PartialEq<IpAddr> for Ipv4Addr { eq(&self, other: &IpAddr) -> bool206 fn eq(&self, other: &IpAddr) -> bool { 207 match other { IpAddr::V4(v4) => self == v4, IpAddr::V6(_) => false, } 208 } 209 } 210 impl Eq for Ipv4Addr {} 211 impl hash::Hash for Ipv4Addr { hash<H: hash::Hasher>(&self, s: &mut H)212 fn hash<H: hash::Hasher>(&self, s: &mut H) { 213 { self.inner.s_addr }.hash(s) 214 } 215 } 216 impl PartialOrd for Ipv4Addr { partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering>217 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { 218 Some(self.cmp(other)) 219 } 220 } 221 impl PartialOrd<Ipv4Addr> for IpAddr { partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering>222 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { 223 match self { 224 IpAddr::V4(v4) => v4.partial_cmp(other), 225 IpAddr::V6(_) => Some(Ordering::Greater), 226 } 227 } 228 } 229 impl PartialOrd<IpAddr> for Ipv4Addr { partial_cmp(&self, other: &IpAddr) -> Option<Ordering>230 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> { 231 match other { 232 IpAddr::V4(v4) => self.partial_cmp(v4), 233 IpAddr::V6(_) => Some(Ordering::Less), 234 } 235 } 236 } 237 impl Ord for Ipv4Addr { cmp(&self, other: &Ipv4Addr) -> Ordering238 fn cmp(&self, other: &Ipv4Addr) -> Ordering { 239 u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr)) 240 } 241 } 242 impl IntoInner<c::in_addr> for Ipv4Addr { into_inner(self) -> c::in_addr243 fn into_inner(self) -> c::in_addr { self.inner } 244 } 245 impl From<Ipv4Addr> for u32 { from(ip: Ipv4Addr) -> u32246 fn from(ip: Ipv4Addr) -> u32 { 247 let ip = ip.octets(); 248 u32::from_be_bytes(ip) 249 } 250 } 251 impl From<u32> for Ipv4Addr { from(ip: u32) -> Ipv4Addr252 fn from(ip: u32) -> Ipv4Addr { Ipv4Addr::from(ip.to_be_bytes()) } 253 } 254 impl From<[u8; 4]> for Ipv4Addr { from(octets: [u8; 4]) -> Ipv4Addr255 fn from(octets: [u8; 4]) -> Ipv4Addr { 256 Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]) 257 } 258 } 259 impl From<[u8; 4]> for IpAddr { from(octets: [u8; 4]) -> IpAddr260 fn from(octets: [u8; 4]) -> IpAddr { IpAddr::V4(Ipv4Addr::from(octets)) } 261 } 262 impl Ipv6Addr { new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr263 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, 264 h: u16) -> Ipv6Addr { 265 let addr16 = 266 [a.to_be(), b.to_be(), c.to_be(), d.to_be(), e.to_be(), f.to_be(), 267 g.to_be(), h.to_be()]; 268 Ipv6Addr { 269 inner: c::in6_addr { 270 s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) }, 271 }, 272 } 273 } 274 pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); 275 pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); segments(&self) -> [u16; 8]276 pub const fn segments(&self) -> [u16; 8] { 277 let [a, b, c, d, e, f, g, h] = 278 unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) }; 279 [u16::from_be(a), u16::from_be(b), u16::from_be(c), u16::from_be(d), 280 u16::from_be(e), u16::from_be(f), u16::from_be(g), 281 u16::from_be(h)] 282 } is_unspecified(&self) -> bool283 pub const fn is_unspecified(&self) -> bool { 284 u128::from_be_bytes(self.octets()) == 285 u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets()) 286 } is_loopback(&self) -> bool287 pub const fn is_loopback(&self) -> bool { 288 u128::from_be_bytes(self.octets()) == 289 u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) 290 } is_global(&self) -> bool291 pub const fn is_global(&self) -> bool { 292 match self.multicast_scope() { 293 Some(Ipv6MulticastScope::Global) => true, 294 None => self.is_unicast_global(), 295 _ => false, 296 } 297 } is_unique_local(&self) -> bool298 pub const fn is_unique_local(&self) -> bool { 299 (self.segments()[0] & 0xfe00) == 0xfc00 300 } is_unicast(&self) -> bool301 pub const fn is_unicast(&self) -> bool { !self.is_multicast() } is_unicast_link_local(&self) -> bool302 pub const fn is_unicast_link_local(&self) -> bool { 303 (self.segments()[0] & 0xffc0) == 0xfe80 304 } is_documentation(&self) -> bool305 pub const fn is_documentation(&self) -> bool { 306 (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) 307 } is_benchmarking(&self) -> bool308 pub const fn is_benchmarking(&self) -> bool { 309 (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && 310 (self.segments()[2] == 0) 311 } is_unicast_global(&self) -> bool312 pub const fn is_unicast_global(&self) -> bool { 313 self.is_unicast() && !self.is_loopback() && 314 !self.is_unicast_link_local() && !self.is_unique_local() && 315 !self.is_unspecified() && !self.is_documentation() 316 } multicast_scope(&self) -> Option<Ipv6MulticastScope>317 pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> { 318 if self.is_multicast() { 319 match self.segments()[0] & 0x000f { 320 1 => Some(Ipv6MulticastScope::InterfaceLocal), 321 2 => Some(Ipv6MulticastScope::LinkLocal), 322 3 => Some(Ipv6MulticastScope::RealmLocal), 323 4 => Some(Ipv6MulticastScope::AdminLocal), 324 5 => Some(Ipv6MulticastScope::SiteLocal), 325 8 => Some(Ipv6MulticastScope::OrganizationLocal), 326 14 => Some(Ipv6MulticastScope::Global), 327 _ => None, 328 } 329 } else { None } 330 } is_multicast(&self) -> bool331 pub const fn is_multicast(&self) -> bool { 332 (self.segments()[0] & 0xff00) == 0xff00 333 } to_ipv4_mapped(&self) -> Option<Ipv4Addr>334 pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> { 335 match self.octets() { 336 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => { 337 Some(Ipv4Addr::new(a, b, c, d)) 338 } 339 _ => None, 340 } 341 } to_ipv4(&self) -> Option<Ipv4Addr>342 pub const fn to_ipv4(&self) -> Option<Ipv4Addr> { 343 if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() { 344 let [a, b] = ab.to_be_bytes(); 345 let [c, d] = cd.to_be_bytes(); 346 Some(Ipv4Addr::new(a, b, c, d)) 347 } else { None } 348 } to_canonical(&self) -> IpAddr349 pub const fn to_canonical(&self) -> IpAddr { 350 if let Some(mapped) = self.to_ipv4_mapped() { 351 return IpAddr::V4(mapped); 352 } 353 IpAddr::V6(*self) 354 } octets(&self) -> [u8; 16]355 pub const fn octets(&self) -> [u8; 16] { self.inner.s6_addr } 356 } 357 impl fmt::Display for Ipv6Addr { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 359 if f.precision().is_none() && f.width().is_none() { 360 let segments = self.segments(); 361 if self.is_unspecified() { 362 f.write_str("::") 363 } else if self.is_loopback() { 364 f.write_str("::1") 365 } else if let Some(ipv4) = self.to_ipv4() { 366 match segments[5] { 367 0 => write!(f, "::{}", ipv4), 368 0xffff => write!(f, "::ffff:{}", ipv4), 369 _ => unreachable!(), 370 } 371 } else { 372 #[derive(Copy, Clone, Default)] 373 struct Span { 374 start: usize, 375 len: usize, 376 } 377 let zeroes = 378 { 379 let mut longest = Span::default(); 380 let mut current = Span::default(); 381 for (i, &segment) in segments.iter().enumerate() { 382 if segment == 0 { 383 if current.len == 0 { current.start = i; } 384 current.len += 1; 385 if current.len > longest.len { longest = current; } 386 } else { current = Span::default(); } 387 } 388 longest 389 }; 390 #[doc = " Write a colon-separated part of the address"] 391 #[inline] 392 fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) 393 -> fmt::Result { 394 if let Some((first, tail)) = chunk.split_first() { 395 write!(f, "{:x}", first)?; 396 for segment in tail { 397 f.write_char(':')?; 398 write!(f, "{:x}", segment)?; 399 } 400 } 401 Ok(()) 402 } 403 if zeroes.len > 1 { 404 fmt_subslice(f, &segments[..zeroes.start])?; 405 f.write_str("::")?; 406 fmt_subslice(f, &segments[zeroes.start + zeroes.len..]) 407 } else { fmt_subslice(f, &segments) } 408 } 409 } else { 410 const IPV6_BUF_LEN: usize = (4 * 8) + 7; 411 let mut buf = [0u8; IPV6_BUF_LEN]; 412 let mut buf_slice = &mut buf[..]; 413 write!(buf_slice, "{}", self).unwrap(); 414 let len = IPV6_BUF_LEN - buf_slice.len(); 415 let buf = 416 unsafe { crate::str::from_utf8_unchecked(&buf[..len]) }; 417 f.pad(buf) 418 } 419 } 420 } 421 impl fmt::Debug for Ipv6Addr { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result422 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 423 fmt::Display::fmt(self, fmt) 424 } 425 } 426 impl Clone for Ipv6Addr { clone(&self) -> Ipv6Addr427 fn clone(&self) -> Ipv6Addr { *self } 428 } 429 impl PartialEq for Ipv6Addr { eq(&self, other: &Ipv6Addr) -> bool430 fn eq(&self, other: &Ipv6Addr) -> bool { 431 self.inner.s6_addr == other.inner.s6_addr 432 } 433 } 434 impl PartialEq<IpAddr> for Ipv6Addr { eq(&self, other: &IpAddr) -> bool435 fn eq(&self, other: &IpAddr) -> bool { 436 match other { IpAddr::V4(_) => false, IpAddr::V6(v6) => self == v6, } 437 } 438 } 439 impl PartialEq<Ipv6Addr> for IpAddr { eq(&self, other: &Ipv6Addr) -> bool440 fn eq(&self, other: &Ipv6Addr) -> bool { 441 match self { IpAddr::V4(_) => false, IpAddr::V6(v6) => v6 == other, } 442 } 443 } 444 impl Eq for Ipv6Addr {} 445 impl hash::Hash for Ipv6Addr { hash<H: hash::Hasher>(&self, s: &mut H)446 fn hash<H: hash::Hasher>(&self, s: &mut H) { self.inner.s6_addr.hash(s) } 447 } 448 impl PartialOrd for Ipv6Addr { partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering>449 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { 450 Some(self.cmp(other)) 451 } 452 } 453 impl PartialOrd<Ipv6Addr> for IpAddr { partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering>454 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { 455 match self { 456 IpAddr::V4(_) => Some(Ordering::Less), 457 IpAddr::V6(v6) => v6.partial_cmp(other), 458 } 459 } 460 } 461 impl PartialOrd<IpAddr> for Ipv6Addr { partial_cmp(&self, other: &IpAddr) -> Option<Ordering>462 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> { 463 match other { 464 IpAddr::V4(_) => Some(Ordering::Greater), 465 IpAddr::V6(v6) => self.partial_cmp(v6), 466 } 467 } 468 } 469 impl Ord for Ipv6Addr { cmp(&self, other: &Ipv6Addr) -> Ordering470 fn cmp(&self, other: &Ipv6Addr) -> Ordering { 471 self.segments().cmp(&other.segments()) 472 } 473 } 474 impl AsInner<c::in6_addr> for Ipv6Addr { as_inner(&self) -> &c::in6_addr475 fn as_inner(&self) -> &c::in6_addr { &self.inner } 476 } 477 impl FromInner<c::in6_addr> for Ipv6Addr { from_inner(addr: c::in6_addr) -> Ipv6Addr478 fn from_inner(addr: c::in6_addr) -> Ipv6Addr { Ipv6Addr { inner: addr } } 479 } 480 impl From<Ipv6Addr> for u128 { from(ip: Ipv6Addr) -> u128481 fn from(ip: Ipv6Addr) -> u128 { 482 let ip = ip.octets(); 483 u128::from_be_bytes(ip) 484 } 485 } 486 impl From<u128> for Ipv6Addr { from(ip: u128) -> Ipv6Addr487 fn from(ip: u128) -> Ipv6Addr { Ipv6Addr::from(ip.to_be_bytes()) } 488 } 489 impl From<[u8; 16]> for Ipv6Addr { from(octets: [u8; 16]) -> Ipv6Addr490 fn from(octets: [u8; 16]) -> Ipv6Addr { 491 let inner = c::in6_addr { s6_addr: octets }; 492 Ipv6Addr::from_inner(inner) 493 } 494 } 495 impl From<[u16; 8]> for Ipv6Addr { from(segments: [u16; 8]) -> Ipv6Addr496 fn from(segments: [u16; 8]) -> Ipv6Addr { 497 let [a, b, c, d, e, f, g, h] = segments; 498 Ipv6Addr::new(a, b, c, d, e, f, g, h) 499 } 500 } 501 impl From<[u8; 16]> for IpAddr { from(octets: [u8; 16]) -> IpAddr502 fn from(octets: [u8; 16]) -> IpAddr { IpAddr::V6(Ipv6Addr::from(octets)) } 503 } 504 impl From<[u16; 8]> for IpAddr { from(segments: [u16; 8]) -> IpAddr505 fn from(segments: [u16; 8]) -> IpAddr { 506 IpAddr::V6(Ipv6Addr::from(segments)) 507 } 508 } 509