1use super::display_buffer::DisplayBuffer;
2use crate::cmp::Ordering;
3use crate::fmt::{self, Write};
4use crate::hash::{Hash, Hasher};
5use crate::mem::transmute;
6use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
7
8#[rustc_diagnostic_item = "IpAddr"]
28#[stable(feature = "ip_addr", since = "1.7.0")]
29#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
30pub enum IpAddr {
31 #[stable(feature = "ip_addr", since = "1.7.0")]
33 V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
34 #[stable(feature = "ip_addr", since = "1.7.0")]
36 V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
37}
38
39#[rustc_diagnostic_item = "Ipv4Addr"]
71#[derive(Copy, Clone, PartialEq, Eq)]
72#[stable(feature = "rust1", since = "1.0.0")]
73pub struct Ipv4Addr {
74 octets: [u8; 4],
75}
76
77#[stable(feature = "rust1", since = "1.0.0")]
78impl Hash for Ipv4Addr {
79 fn hash<H: Hasher>(&self, state: &mut H) {
80 u32::from_ne_bytes(self.octets).hash(state);
84 }
85}
86
87#[rustc_diagnostic_item = "Ipv6Addr"]
164#[derive(Copy, Clone, PartialEq, Eq)]
165#[stable(feature = "rust1", since = "1.0.0")]
166pub struct Ipv6Addr {
167 octets: [u8; 16],
168}
169
170#[stable(feature = "rust1", since = "1.0.0")]
171impl Hash for Ipv6Addr {
172 fn hash<H: Hasher>(&self, state: &mut H) {
173 u128::from_ne_bytes(self.octets).hash(state);
177 }
178}
179
180#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
216#[unstable(feature = "ip", issue = "27709")]
217#[non_exhaustive]
218pub enum Ipv6MulticastScope {
219 InterfaceLocal,
221 LinkLocal,
223 RealmLocal,
225 AdminLocal,
227 SiteLocal,
229 OrganizationLocal,
231 Global,
233}
234
235impl IpAddr {
236 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
250 #[stable(feature = "ip_shared", since = "1.12.0")]
251 #[must_use]
252 #[inline]
253 pub const fn is_unspecified(&self) -> bool {
254 match self {
255 IpAddr::V4(ip) => ip.is_unspecified(),
256 IpAddr::V6(ip) => ip.is_unspecified(),
257 }
258 }
259
260 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
274 #[stable(feature = "ip_shared", since = "1.12.0")]
275 #[must_use]
276 #[inline]
277 pub const fn is_loopback(&self) -> bool {
278 match self {
279 IpAddr::V4(ip) => ip.is_loopback(),
280 IpAddr::V6(ip) => ip.is_loopback(),
281 }
282 }
283
284 #[unstable(feature = "ip", issue = "27709")]
300 #[must_use]
301 #[inline]
302 pub const fn is_global(&self) -> bool {
303 match self {
304 IpAddr::V4(ip) => ip.is_global(),
305 IpAddr::V6(ip) => ip.is_global(),
306 }
307 }
308
309 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
323 #[stable(feature = "ip_shared", since = "1.12.0")]
324 #[must_use]
325 #[inline]
326 pub const fn is_multicast(&self) -> bool {
327 match self {
328 IpAddr::V4(ip) => ip.is_multicast(),
329 IpAddr::V6(ip) => ip.is_multicast(),
330 }
331 }
332
333 #[unstable(feature = "ip", issue = "27709")]
352 #[must_use]
353 #[inline]
354 pub const fn is_documentation(&self) -> bool {
355 match self {
356 IpAddr::V4(ip) => ip.is_documentation(),
357 IpAddr::V6(ip) => ip.is_documentation(),
358 }
359 }
360
361 #[unstable(feature = "ip", issue = "27709")]
377 #[must_use]
378 #[inline]
379 pub const fn is_benchmarking(&self) -> bool {
380 match self {
381 IpAddr::V4(ip) => ip.is_benchmarking(),
382 IpAddr::V6(ip) => ip.is_benchmarking(),
383 }
384 }
385
386 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
400 #[stable(feature = "ipaddr_checker", since = "1.16.0")]
401 #[must_use]
402 #[inline]
403 pub const fn is_ipv4(&self) -> bool {
404 matches!(self, IpAddr::V4(_))
405 }
406
407 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
421 #[stable(feature = "ipaddr_checker", since = "1.16.0")]
422 #[must_use]
423 #[inline]
424 pub const fn is_ipv6(&self) -> bool {
425 matches!(self, IpAddr::V6(_))
426 }
427
428 #[inline]
445 #[must_use = "this returns the result of the operation, \
446 without modifying the original"]
447 #[stable(feature = "ip_to_canonical", since = "1.75.0")]
448 #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")]
449 pub const fn to_canonical(&self) -> IpAddr {
450 match self {
451 IpAddr::V4(_) => *self,
452 IpAddr::V6(v6) => v6.to_canonical(),
453 }
454 }
455
456 #[unstable(feature = "ip_as_octets", issue = "137259")]
470 #[inline]
471 pub const fn as_octets(&self) -> &[u8] {
472 match self {
473 IpAddr::V4(ip) => ip.as_octets().as_slice(),
474 IpAddr::V6(ip) => ip.as_octets().as_slice(),
475 }
476 }
477}
478
479impl Ipv4Addr {
480 #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
492 #[stable(feature = "rust1", since = "1.0.0")]
493 #[must_use]
494 #[inline]
495 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
496 Ipv4Addr { octets: [a, b, c, d] }
497 }
498
499 #[stable(feature = "ip_bits", since = "1.80.0")]
509 pub const BITS: u32 = 32;
510
511 #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
537 #[stable(feature = "ip_bits", since = "1.80.0")]
538 #[must_use]
539 #[inline]
540 pub const fn to_bits(self) -> u32 {
541 u32::from_be_bytes(self.octets)
542 }
543
544 #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
557 #[stable(feature = "ip_bits", since = "1.80.0")]
558 #[must_use]
559 #[inline]
560 pub const fn from_bits(bits: u32) -> Ipv4Addr {
561 Ipv4Addr { octets: bits.to_be_bytes() }
562 }
563
564 #[stable(feature = "ip_constructors", since = "1.30.0")]
575 pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
576
577 #[doc(alias = "INADDR_ANY")]
590 #[stable(feature = "ip_constructors", since = "1.30.0")]
591 pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
592
593 #[stable(feature = "ip_constructors", since = "1.30.0")]
604 pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
605
606 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
617 #[stable(feature = "rust1", since = "1.0.0")]
618 #[must_use]
619 #[inline]
620 pub const fn octets(&self) -> [u8; 4] {
621 self.octets
622 }
623
624 #[unstable(feature = "ip_from", issue = "131360")]
636 #[must_use]
637 #[inline]
638 pub const fn from_octets(octets: [u8; 4]) -> Ipv4Addr {
639 Ipv4Addr { octets }
640 }
641
642 #[unstable(feature = "ip_as_octets", issue = "137259")]
656 #[inline]
657 pub const fn as_octets(&self) -> &[u8; 4] {
658 &self.octets
659 }
660
661 #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
677 #[stable(feature = "ip_shared", since = "1.12.0")]
678 #[must_use]
679 #[inline]
680 pub const fn is_unspecified(&self) -> bool {
681 u32::from_be_bytes(self.octets) == 0
682 }
683
684 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
699 #[stable(since = "1.7.0", feature = "ip_17")]
700 #[must_use]
701 #[inline]
702 pub const fn is_loopback(&self) -> bool {
703 self.octets()[0] == 127
704 }
705
706 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
730 #[stable(since = "1.7.0", feature = "ip_17")]
731 #[must_use]
732 #[inline]
733 pub const fn is_private(&self) -> bool {
734 match self.octets() {
735 [10, ..] => true,
736 [172, b, ..] if b >= 16 && b <= 31 => true,
737 [192, 168, ..] => true,
738 _ => false,
739 }
740 }
741
742 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
758 #[stable(since = "1.7.0", feature = "ip_17")]
759 #[must_use]
760 #[inline]
761 pub const fn is_link_local(&self) -> bool {
762 matches!(self.octets(), [169, 254, ..])
763 }
764
765 #[unstable(feature = "ip", issue = "27709")]
837 #[must_use]
838 #[inline]
839 pub const fn is_global(&self) -> bool {
840 !(self.octets()[0] == 0 || self.is_private()
842 || self.is_shared()
843 || self.is_loopback()
844 || self.is_link_local()
845 || (
848 self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
849 && self.octets()[3] != 9 && self.octets()[3] != 10
850 )
851 || self.is_documentation()
852 || self.is_benchmarking()
853 || self.is_reserved()
854 || self.is_broadcast())
855 }
856
857 #[unstable(feature = "ip", issue = "27709")]
873 #[must_use]
874 #[inline]
875 pub const fn is_shared(&self) -> bool {
876 self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
877 }
878
879 #[unstable(feature = "ip", issue = "27709")]
900 #[must_use]
901 #[inline]
902 pub const fn is_benchmarking(&self) -> bool {
903 self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
904 }
905
906 #[unstable(feature = "ip", issue = "27709")]
936 #[must_use]
937 #[inline]
938 pub const fn is_reserved(&self) -> bool {
939 self.octets()[0] & 240 == 240 && !self.is_broadcast()
940 }
941
942 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
959 #[stable(since = "1.7.0", feature = "ip_17")]
960 #[must_use]
961 #[inline]
962 pub const fn is_multicast(&self) -> bool {
963 self.octets()[0] >= 224 && self.octets()[0] <= 239
964 }
965
966 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
981 #[stable(since = "1.7.0", feature = "ip_17")]
982 #[must_use]
983 #[inline]
984 pub const fn is_broadcast(&self) -> bool {
985 u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
986 }
987
988 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1009 #[stable(since = "1.7.0", feature = "ip_17")]
1010 #[must_use]
1011 #[inline]
1012 pub const fn is_documentation(&self) -> bool {
1013 matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
1014 }
1015
1016 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1037 #[stable(feature = "rust1", since = "1.0.0")]
1038 #[must_use = "this returns the result of the operation, \
1039 without modifying the original"]
1040 #[inline]
1041 pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
1042 let [a, b, c, d] = self.octets();
1043 Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] }
1044 }
1045
1046 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1062 #[stable(feature = "rust1", since = "1.0.0")]
1063 #[must_use = "this returns the result of the operation, \
1064 without modifying the original"]
1065 #[inline]
1066 pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
1067 let [a, b, c, d] = self.octets();
1068 Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] }
1069 }
1070}
1071
1072#[stable(feature = "ip_addr", since = "1.7.0")]
1073impl fmt::Display for IpAddr {
1074 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1075 match self {
1076 IpAddr::V4(ip) => ip.fmt(fmt),
1077 IpAddr::V6(ip) => ip.fmt(fmt),
1078 }
1079 }
1080}
1081
1082#[stable(feature = "ip_addr", since = "1.7.0")]
1083impl fmt::Debug for IpAddr {
1084 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1085 fmt::Display::fmt(self, fmt)
1086 }
1087}
1088
1089#[stable(feature = "ip_from_ip", since = "1.16.0")]
1090#[rustc_const_unstable(feature = "const_try", issue = "74935")]
1091impl const From<Ipv4Addr> for IpAddr {
1092 #[inline]
1107 fn from(ipv4: Ipv4Addr) -> IpAddr {
1108 IpAddr::V4(ipv4)
1109 }
1110}
1111
1112#[stable(feature = "ip_from_ip", since = "1.16.0")]
1113#[rustc_const_unstable(feature = "const_try", issue = "74935")]
1114impl const From<Ipv6Addr> for IpAddr {
1115 #[inline]
1130 fn from(ipv6: Ipv6Addr) -> IpAddr {
1131 IpAddr::V6(ipv6)
1132 }
1133}
1134
1135#[stable(feature = "rust1", since = "1.0.0")]
1136impl fmt::Display for Ipv4Addr {
1137 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1138 let octets = self.octets();
1139
1140 if fmt.precision().is_none() && fmt.width().is_none() {
1143 write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
1144 } else {
1145 const LONGEST_IPV4_ADDR: &str = "255.255.255.255";
1146
1147 let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
1148 write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
1150
1151 fmt.pad(buf.as_str())
1152 }
1153 }
1154}
1155
1156#[stable(feature = "rust1", since = "1.0.0")]
1157impl fmt::Debug for Ipv4Addr {
1158 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1159 fmt::Display::fmt(self, fmt)
1160 }
1161}
1162
1163#[stable(feature = "ip_cmp", since = "1.16.0")]
1164impl PartialEq<Ipv4Addr> for IpAddr {
1165 #[inline]
1166 fn eq(&self, other: &Ipv4Addr) -> bool {
1167 match self {
1168 IpAddr::V4(v4) => v4 == other,
1169 IpAddr::V6(_) => false,
1170 }
1171 }
1172}
1173
1174#[stable(feature = "ip_cmp", since = "1.16.0")]
1175impl PartialEq<IpAddr> for Ipv4Addr {
1176 #[inline]
1177 fn eq(&self, other: &IpAddr) -> bool {
1178 match other {
1179 IpAddr::V4(v4) => self == v4,
1180 IpAddr::V6(_) => false,
1181 }
1182 }
1183}
1184
1185#[stable(feature = "rust1", since = "1.0.0")]
1186impl PartialOrd for Ipv4Addr {
1187 #[inline]
1188 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
1189 Some(self.cmp(other))
1190 }
1191}
1192
1193#[stable(feature = "ip_cmp", since = "1.16.0")]
1194impl PartialOrd<Ipv4Addr> for IpAddr {
1195 #[inline]
1196 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
1197 match self {
1198 IpAddr::V4(v4) => v4.partial_cmp(other),
1199 IpAddr::V6(_) => Some(Ordering::Greater),
1200 }
1201 }
1202}
1203
1204#[stable(feature = "ip_cmp", since = "1.16.0")]
1205impl PartialOrd<IpAddr> for Ipv4Addr {
1206 #[inline]
1207 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
1208 match other {
1209 IpAddr::V4(v4) => self.partial_cmp(v4),
1210 IpAddr::V6(_) => Some(Ordering::Less),
1211 }
1212 }
1213}
1214
1215#[stable(feature = "rust1", since = "1.0.0")]
1216impl Ord for Ipv4Addr {
1217 #[inline]
1218 fn cmp(&self, other: &Ipv4Addr) -> Ordering {
1219 self.octets.cmp(&other.octets)
1220 }
1221}
1222
1223#[stable(feature = "ip_u32", since = "1.1.0")]
1224#[rustc_const_unstable(feature = "const_try", issue = "74935")]
1225impl const From<Ipv4Addr> for u32 {
1226 #[inline]
1228 fn from(ip: Ipv4Addr) -> u32 {
1229 ip.to_bits()
1230 }
1231}
1232
1233#[stable(feature = "ip_u32", since = "1.1.0")]
1234#[rustc_const_unstable(feature = "const_try", issue = "74935")]
1235impl const From<u32> for Ipv4Addr {
1236 #[inline]
1238 fn from(ip: u32) -> Ipv4Addr {
1239 Ipv4Addr::from_bits(ip)
1240 }
1241}
1242
1243#[stable(feature = "from_slice_v4", since = "1.9.0")]
1244#[rustc_const_unstable(feature = "const_try", issue = "74935")]
1245impl const From<[u8; 4]> for Ipv4Addr {
1246 #[inline]
1257 fn from(octets: [u8; 4]) -> Ipv4Addr {
1258 Ipv4Addr { octets }
1259 }
1260}
1261
1262#[stable(feature = "ip_from_slice", since = "1.17.0")]
1263#[rustc_const_unstable(feature = "const_try", issue = "74935")]
1264impl const From<[u8; 4]> for IpAddr {
1265 #[inline]
1276 fn from(octets: [u8; 4]) -> IpAddr {
1277 IpAddr::V4(Ipv4Addr::from(octets))
1278 }
1279}
1280
1281impl Ipv6Addr {
1282 #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
1294 #[stable(feature = "rust1", since = "1.0.0")]
1295 #[must_use]
1296 #[inline]
1297 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
1298 let addr16 = [
1299 a.to_be(),
1300 b.to_be(),
1301 c.to_be(),
1302 d.to_be(),
1303 e.to_be(),
1304 f.to_be(),
1305 g.to_be(),
1306 h.to_be(),
1307 ];
1308 Ipv6Addr {
1309 octets: unsafe { transmute::<_, [u8; 16]>(addr16) },
1312 }
1313 }
1314
1315 #[stable(feature = "ip_bits", since = "1.80.0")]
1325 pub const BITS: u32 = 128;
1326
1327 #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
1364 #[stable(feature = "ip_bits", since = "1.80.0")]
1365 #[must_use]
1366 #[inline]
1367 pub const fn to_bits(self) -> u128 {
1368 u128::from_be_bytes(self.octets)
1369 }
1370
1371 #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
1389 #[stable(feature = "ip_bits", since = "1.80.0")]
1390 #[must_use]
1391 #[inline]
1392 pub const fn from_bits(bits: u128) -> Ipv6Addr {
1393 Ipv6Addr { octets: bits.to_be_bytes() }
1394 }
1395
1396 #[doc(alias = "IN6ADDR_LOOPBACK_INIT")]
1410 #[doc(alias = "in6addr_loopback")]
1411 #[stable(feature = "ip_constructors", since = "1.30.0")]
1412 pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
1413
1414 #[doc(alias = "IN6ADDR_ANY_INIT")]
1427 #[doc(alias = "in6addr_any")]
1428 #[stable(feature = "ip_constructors", since = "1.30.0")]
1429 pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
1430
1431 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1442 #[stable(feature = "rust1", since = "1.0.0")]
1443 #[must_use]
1444 #[inline]
1445 pub const fn segments(&self) -> [u16; 8] {
1446 let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) };
1449 [
1451 u16::from_be(a),
1452 u16::from_be(b),
1453 u16::from_be(c),
1454 u16::from_be(d),
1455 u16::from_be(e),
1456 u16::from_be(f),
1457 u16::from_be(g),
1458 u16::from_be(h),
1459 ]
1460 }
1461
1462 #[unstable(feature = "ip_from", issue = "131360")]
1483 #[must_use]
1484 #[inline]
1485 pub const fn from_segments(segments: [u16; 8]) -> Ipv6Addr {
1486 let [a, b, c, d, e, f, g, h] = segments;
1487 Ipv6Addr::new(a, b, c, d, e, f, g, h)
1488 }
1489
1490 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1505 #[stable(since = "1.7.0", feature = "ip_17")]
1506 #[must_use]
1507 #[inline]
1508 pub const fn is_unspecified(&self) -> bool {
1509 u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
1510 }
1511
1512 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1529 #[stable(since = "1.7.0", feature = "ip_17")]
1530 #[must_use]
1531 #[inline]
1532 pub const fn is_loopback(&self) -> bool {
1533 u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
1534 }
1535
1536 #[unstable(feature = "ip", issue = "27709")]
1602 #[must_use]
1603 #[inline]
1604 pub const fn is_global(&self) -> bool {
1605 !(self.is_unspecified()
1606 || self.is_loopback()
1607 || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
1609 || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
1611 || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _])
1613 || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
1615 && !(
1616 u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
1618 || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
1620 || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _])
1622 || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
1624 || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x3F)
1627 ))
1628 || matches!(self.segments(), [0x2002, _, _, _, _, _, _, _])
1631 || self.is_documentation()
1632 || matches!(self.segments(), [0x5f00, ..])
1634 || self.is_unique_local()
1635 || self.is_unicast_link_local())
1636 }
1637
1638 #[must_use]
1653 #[inline]
1654 #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")]
1655 #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")]
1656 pub const fn is_unique_local(&self) -> bool {
1657 (self.segments()[0] & 0xfe00) == 0xfc00
1658 }
1659
1660 #[unstable(feature = "ip", issue = "27709")]
1682 #[must_use]
1683 #[inline]
1684 pub const fn is_unicast(&self) -> bool {
1685 !self.is_multicast()
1686 }
1687
1688 #[must_use]
1731 #[inline]
1732 #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")]
1733 #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")]
1734 pub const fn is_unicast_link_local(&self) -> bool {
1735 (self.segments()[0] & 0xffc0) == 0xfe80
1736 }
1737
1738 #[unstable(feature = "ip", issue = "27709")]
1758 #[must_use]
1759 #[inline]
1760 pub const fn is_documentation(&self) -> bool {
1761 matches!(self.segments(), [0x2001, 0xdb8, ..] | [0x3fff, 0..=0x0fff, ..])
1762 }
1763
1764 #[unstable(feature = "ip", issue = "27709")]
1781 #[must_use]
1782 #[inline]
1783 pub const fn is_benchmarking(&self) -> bool {
1784 (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0)
1785 }
1786
1787 #[unstable(feature = "ip", issue = "27709")]
1818 #[must_use]
1819 #[inline]
1820 pub const fn is_unicast_global(&self) -> bool {
1821 self.is_unicast()
1822 && !self.is_loopback()
1823 && !self.is_unicast_link_local()
1824 && !self.is_unique_local()
1825 && !self.is_unspecified()
1826 && !self.is_documentation()
1827 && !self.is_benchmarking()
1828 }
1829
1830 #[unstable(feature = "ip", issue = "27709")]
1846 #[must_use]
1847 #[inline]
1848 pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
1849 if self.is_multicast() {
1850 match self.segments()[0] & 0x000f {
1851 1 => Some(Ipv6MulticastScope::InterfaceLocal),
1852 2 => Some(Ipv6MulticastScope::LinkLocal),
1853 3 => Some(Ipv6MulticastScope::RealmLocal),
1854 4 => Some(Ipv6MulticastScope::AdminLocal),
1855 5 => Some(Ipv6MulticastScope::SiteLocal),
1856 8 => Some(Ipv6MulticastScope::OrganizationLocal),
1857 14 => Some(Ipv6MulticastScope::Global),
1858 _ => None,
1859 }
1860 } else {
1861 None
1862 }
1863 }
1864
1865 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1880 #[stable(since = "1.7.0", feature = "ip_17")]
1881 #[must_use]
1882 #[inline]
1883 pub const fn is_multicast(&self) -> bool {
1884 (self.segments()[0] & 0xff00) == 0xff00
1885 }
1886
1887 #[unstable(feature = "ip", issue = "27709")]
1905 #[must_use]
1906 #[inline]
1907 pub const fn is_ipv4_mapped(&self) -> bool {
1908 matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
1909 }
1910
1911 #[inline]
1932 #[must_use = "this returns the result of the operation, \
1933 without modifying the original"]
1934 #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
1935 #[rustc_const_stable(feature = "const_ipv6_to_ipv4_mapped", since = "1.75.0")]
1936 pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
1937 match self.octets() {
1938 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
1939 Some(Ipv4Addr::new(a, b, c, d))
1940 }
1941 _ => None,
1942 }
1943 }
1944
1945 #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1974 #[stable(feature = "rust1", since = "1.0.0")]
1975 #[must_use = "this returns the result of the operation, \
1976 without modifying the original"]
1977 #[inline]
1978 pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
1979 if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
1980 let [a, b] = ab.to_be_bytes();
1981 let [c, d] = cd.to_be_bytes();
1982 Some(Ipv4Addr::new(a, b, c, d))
1983 } else {
1984 None
1985 }
1986 }
1987
1988 #[inline]
2000 #[must_use = "this returns the result of the operation, \
2001 without modifying the original"]
2002 #[stable(feature = "ip_to_canonical", since = "1.75.0")]
2003 #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")]
2004 pub const fn to_canonical(&self) -> IpAddr {
2005 if let Some(mapped) = self.to_ipv4_mapped() {
2006 return IpAddr::V4(mapped);
2007 }
2008 IpAddr::V6(*self)
2009 }
2010
2011 #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
2020 #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
2021 #[must_use]
2022 #[inline]
2023 pub const fn octets(&self) -> [u8; 16] {
2024 self.octets
2025 }
2026
2027 #[unstable(feature = "ip_from", issue = "131360")]
2048 #[must_use]
2049 #[inline]
2050 pub const fn from_octets(octets: [u8; 16]) -> Ipv6Addr {
2051 Ipv6Addr { octets }
2052 }
2053
2054 #[unstable(feature = "ip_as_octets", issue = "137259")]
2068 #[inline]
2069 pub const fn as_octets(&self) -> &[u8; 16] {
2070 &self.octets
2071 }
2072}
2073
2074#[stable(feature = "rust1", since = "1.0.0")]
2077impl fmt::Display for Ipv6Addr {
2078 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2079 if f.precision().is_none() && f.width().is_none() {
2082 let segments = self.segments();
2083
2084 if let Some(ipv4) = self.to_ipv4_mapped() {
2085 write!(f, "::ffff:{}", ipv4)
2086 } else {
2087 #[derive(Copy, Clone, Default)]
2088 struct Span {
2089 start: usize,
2090 len: usize,
2091 }
2092
2093 let zeroes = {
2095 let mut longest = Span::default();
2096 let mut current = Span::default();
2097
2098 for (i, &segment) in segments.iter().enumerate() {
2099 if segment == 0 {
2100 if current.len == 0 {
2101 current.start = i;
2102 }
2103
2104 current.len += 1;
2105
2106 if current.len > longest.len {
2107 longest = current;
2108 }
2109 } else {
2110 current = Span::default();
2111 }
2112 }
2113
2114 longest
2115 };
2116
2117 #[inline]
2119 fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
2120 if let Some((first, tail)) = chunk.split_first() {
2121 write!(f, "{:x}", first)?;
2122 for segment in tail {
2123 f.write_char(':')?;
2124 write!(f, "{:x}", segment)?;
2125 }
2126 }
2127 Ok(())
2128 }
2129
2130 if zeroes.len > 1 {
2131 fmt_subslice(f, &segments[..zeroes.start])?;
2132 f.write_str("::")?;
2133 fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
2134 } else {
2135 fmt_subslice(f, &segments)
2136 }
2137 }
2138 } else {
2139 const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
2140
2141 let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
2142 write!(buf, "{}", self).unwrap();
2144
2145 f.pad(buf.as_str())
2146 }
2147 }
2148}
2149
2150#[stable(feature = "rust1", since = "1.0.0")]
2151impl fmt::Debug for Ipv6Addr {
2152 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2153 fmt::Display::fmt(self, fmt)
2154 }
2155}
2156
2157#[stable(feature = "ip_cmp", since = "1.16.0")]
2158impl PartialEq<IpAddr> for Ipv6Addr {
2159 #[inline]
2160 fn eq(&self, other: &IpAddr) -> bool {
2161 match other {
2162 IpAddr::V4(_) => false,
2163 IpAddr::V6(v6) => self == v6,
2164 }
2165 }
2166}
2167
2168#[stable(feature = "ip_cmp", since = "1.16.0")]
2169impl PartialEq<Ipv6Addr> for IpAddr {
2170 #[inline]
2171 fn eq(&self, other: &Ipv6Addr) -> bool {
2172 match self {
2173 IpAddr::V4(_) => false,
2174 IpAddr::V6(v6) => v6 == other,
2175 }
2176 }
2177}
2178
2179#[stable(feature = "rust1", since = "1.0.0")]
2180impl PartialOrd for Ipv6Addr {
2181 #[inline]
2182 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
2183 Some(self.cmp(other))
2184 }
2185}
2186
2187#[stable(feature = "ip_cmp", since = "1.16.0")]
2188impl PartialOrd<Ipv6Addr> for IpAddr {
2189 #[inline]
2190 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
2191 match self {
2192 IpAddr::V4(_) => Some(Ordering::Less),
2193 IpAddr::V6(v6) => v6.partial_cmp(other),
2194 }
2195 }
2196}
2197
2198#[stable(feature = "ip_cmp", since = "1.16.0")]
2199impl PartialOrd<IpAddr> for Ipv6Addr {
2200 #[inline]
2201 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
2202 match other {
2203 IpAddr::V4(_) => Some(Ordering::Greater),
2204 IpAddr::V6(v6) => self.partial_cmp(v6),
2205 }
2206 }
2207}
2208
2209#[stable(feature = "rust1", since = "1.0.0")]
2210impl Ord for Ipv6Addr {
2211 #[inline]
2212 fn cmp(&self, other: &Ipv6Addr) -> Ordering {
2213 self.segments().cmp(&other.segments())
2214 }
2215}
2216
2217#[stable(feature = "i128", since = "1.26.0")]
2218#[rustc_const_unstable(feature = "const_try", issue = "74935")]
2219impl const From<Ipv6Addr> for u128 {
2220 #[inline]
2222 fn from(ip: Ipv6Addr) -> u128 {
2223 ip.to_bits()
2224 }
2225}
2226#[stable(feature = "i128", since = "1.26.0")]
2227#[rustc_const_unstable(feature = "const_try", issue = "74935")]
2228impl const From<u128> for Ipv6Addr {
2229 #[inline]
2231 fn from(ip: u128) -> Ipv6Addr {
2232 Ipv6Addr::from_bits(ip)
2233 }
2234}
2235
2236#[stable(feature = "ipv6_from_octets", since = "1.9.0")]
2237#[rustc_const_unstable(feature = "const_try", issue = "74935")]
2238impl const From<[u8; 16]> for Ipv6Addr {
2239 #[inline]
2259 fn from(octets: [u8; 16]) -> Ipv6Addr {
2260 Ipv6Addr { octets }
2261 }
2262}
2263
2264#[stable(feature = "ipv6_from_segments", since = "1.16.0")]
2265#[rustc_const_unstable(feature = "const_try", issue = "74935")]
2266impl const From<[u16; 8]> for Ipv6Addr {
2267 #[inline]
2287 fn from(segments: [u16; 8]) -> Ipv6Addr {
2288 let [a, b, c, d, e, f, g, h] = segments;
2289 Ipv6Addr::new(a, b, c, d, e, f, g, h)
2290 }
2291}
2292
2293#[stable(feature = "ip_from_slice", since = "1.17.0")]
2294#[rustc_const_unstable(feature = "const_try", issue = "74935")]
2295impl const From<[u8; 16]> for IpAddr {
2296 #[inline]
2316 fn from(octets: [u8; 16]) -> IpAddr {
2317 IpAddr::V6(Ipv6Addr::from(octets))
2318 }
2319}
2320
2321#[stable(feature = "ip_from_slice", since = "1.17.0")]
2322#[rustc_const_unstable(feature = "const_try", issue = "74935")]
2323impl const From<[u16; 8]> for IpAddr {
2324 #[inline]
2344 fn from(segments: [u16; 8]) -> IpAddr {
2345 IpAddr::V6(Ipv6Addr::from(segments))
2346 }
2347}
2348
2349#[stable(feature = "ip_bitops", since = "1.75.0")]
2350#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2351impl const Not for Ipv4Addr {
2352 type Output = Ipv4Addr;
2353
2354 #[inline]
2355 fn not(mut self) -> Ipv4Addr {
2356 let mut idx = 0;
2357 while idx < 4 {
2358 self.octets[idx] = !self.octets[idx];
2359 idx += 1;
2360 }
2361 self
2362 }
2363}
2364
2365#[stable(feature = "ip_bitops", since = "1.75.0")]
2366#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2367impl const Not for &'_ Ipv4Addr {
2368 type Output = Ipv4Addr;
2369
2370 #[inline]
2371 fn not(self) -> Ipv4Addr {
2372 !*self
2373 }
2374}
2375
2376#[stable(feature = "ip_bitops", since = "1.75.0")]
2377#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2378impl const Not for Ipv6Addr {
2379 type Output = Ipv6Addr;
2380
2381 #[inline]
2382 fn not(mut self) -> Ipv6Addr {
2383 let mut idx = 0;
2384 while idx < 16 {
2385 self.octets[idx] = !self.octets[idx];
2386 idx += 1;
2387 }
2388 self
2389 }
2390}
2391
2392#[stable(feature = "ip_bitops", since = "1.75.0")]
2393#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2394impl const Not for &'_ Ipv6Addr {
2395 type Output = Ipv6Addr;
2396
2397 #[inline]
2398 fn not(self) -> Ipv6Addr {
2399 !*self
2400 }
2401}
2402
2403macro_rules! bitop_impls {
2404 ($(
2405 $(#[$attr:meta])*
2406 impl ($BitOp:ident, $BitOpAssign:ident) for $ty:ty = ($bitop:ident, $bitop_assign:ident);
2407 )*) => {
2408 $(
2409 $(#[$attr])*
2410 impl const $BitOpAssign for $ty {
2411 fn $bitop_assign(&mut self, rhs: $ty) {
2412 let mut idx = 0;
2413 while idx < self.octets.len() {
2414 self.octets[idx].$bitop_assign(rhs.octets[idx]);
2415 idx += 1;
2416 }
2417 }
2418 }
2419
2420 $(#[$attr])*
2421 impl const $BitOpAssign<&'_ $ty> for $ty {
2422 fn $bitop_assign(&mut self, rhs: &'_ $ty) {
2423 self.$bitop_assign(*rhs);
2424 }
2425 }
2426
2427 $(#[$attr])*
2428 impl const $BitOp for $ty {
2429 type Output = $ty;
2430
2431 #[inline]
2432 fn $bitop(mut self, rhs: $ty) -> $ty {
2433 self.$bitop_assign(rhs);
2434 self
2435 }
2436 }
2437
2438 $(#[$attr])*
2439 impl const $BitOp<&'_ $ty> for $ty {
2440 type Output = $ty;
2441
2442 #[inline]
2443 fn $bitop(mut self, rhs: &'_ $ty) -> $ty {
2444 self.$bitop_assign(*rhs);
2445 self
2446 }
2447 }
2448
2449 $(#[$attr])*
2450 impl const $BitOp<$ty> for &'_ $ty {
2451 type Output = $ty;
2452
2453 #[inline]
2454 fn $bitop(self, rhs: $ty) -> $ty {
2455 let mut lhs = *self;
2456 lhs.$bitop_assign(rhs);
2457 lhs
2458 }
2459 }
2460
2461 $(#[$attr])*
2462 impl const $BitOp<&'_ $ty> for &'_ $ty {
2463 type Output = $ty;
2464
2465 #[inline]
2466 fn $bitop(self, rhs: &'_ $ty) -> $ty {
2467 let mut lhs = *self;
2468 lhs.$bitop_assign(*rhs);
2469 lhs
2470 }
2471 }
2472 )*
2473 };
2474}
2475
2476bitop_impls! {
2477 #[stable(feature = "ip_bitops", since = "1.75.0")]
2478 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2479 impl (BitAnd, BitAndAssign) for Ipv4Addr = (bitand, bitand_assign);
2480 #[stable(feature = "ip_bitops", since = "1.75.0")]
2481 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2482 impl (BitOr, BitOrAssign) for Ipv4Addr = (bitor, bitor_assign);
2483
2484 #[stable(feature = "ip_bitops", since = "1.75.0")]
2485 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2486 impl (BitAnd, BitAndAssign) for Ipv6Addr = (bitand, bitand_assign);
2487 #[stable(feature = "ip_bitops", since = "1.75.0")]
2488 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2489 impl (BitOr, BitOrAssign) for Ipv6Addr = (bitor, bitor_assign);
2490}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4