1use std::{
4 net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr},
5 num::ParseIntError,
6};
7
8#[cfg(feature = "ula")]
9use {
10 rand::Rng,
11 std::time::{SystemTime, SystemTimeError},
12};
13
14#[derive(Debug, Clone, PartialEq)]
16pub struct IpNetPrefixError(u8);
17
18impl std::fmt::Display for IpNetPrefixError {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 write!(f, "invalid network prefix {}", self.0)
21 }
22}
23impl std::error::Error for IpNetPrefixError {}
24
25#[derive(Debug, Clone)]
27pub enum IpNetParseError {
28 InvalidAddr(AddrParseError),
30 PrefixValue(IpNetPrefixError),
32 NoPrefix,
34 InvalidPrefix(ParseIntError),
36}
37
38impl std::fmt::Display for IpNetParseError {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 match self {
41 IpNetParseError::InvalidAddr(e) => e.fmt(f),
42 IpNetParseError::PrefixValue(e) => {
43 write!(f, "invalid prefix value: {e}")
44 }
45 IpNetParseError::NoPrefix => write!(f, "missing '/' character"),
46 IpNetParseError::InvalidPrefix(e) => e.fmt(f),
47 }
48 }
49}
50impl std::error::Error for IpNetParseError {}
51
52#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
54#[cfg_attr(feature = "serde", serde(untagged))]
55#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
56pub enum IpNet {
57 V4(Ipv4Net),
59 V6(Ipv6Net),
61}
62
63impl IpNet {
64 pub fn new(addr: IpAddr, prefix: u8) -> Result<Self, IpNetPrefixError> {
66 match addr {
67 IpAddr::V4(addr) => Ok(Self::V4(Ipv4Net::new(addr, prefix)?)),
68 IpAddr::V6(addr) => Ok(Self::V6(Ipv6Net::new(addr, prefix)?)),
69 }
70 }
71
72 pub const fn new_unchecked(addr: IpAddr, prefix: u8) -> Self {
75 match addr {
76 IpAddr::V4(addr) => Self::V4(Ipv4Net::new_unchecked(addr, prefix)),
77 IpAddr::V6(addr) => Self::V6(Ipv6Net::new_unchecked(addr, prefix)),
78 }
79 }
80
81 pub fn host_net(addr: IpAddr) -> Self {
83 match addr {
84 IpAddr::V4(addr) => Self::V4(Ipv4Net::host_net(addr)),
85 IpAddr::V6(addr) => Self::V6(Ipv6Net::host_net(addr)),
86 }
87 }
88
89 pub const fn addr(&self) -> IpAddr {
91 match self {
92 IpNet::V4(inner) => IpAddr::V4(inner.addr()),
93 IpNet::V6(inner) => IpAddr::V6(inner.addr()),
94 }
95 }
96
97 pub fn prefix(&self) -> IpAddr {
99 match self {
100 IpNet::V4(inner) => inner.prefix().into(),
101 IpNet::V6(inner) => inner.prefix().into(),
102 }
103 }
104
105 pub const fn width(&self) -> u8 {
107 match self {
108 IpNet::V4(inner) => inner.width(),
109 IpNet::V6(inner) => inner.width(),
110 }
111 }
112
113 pub fn mask_addr(&self) -> IpAddr {
115 match self {
116 IpNet::V4(inner) => inner.mask_addr().into(),
117 IpNet::V6(inner) => inner.mask_addr().into(),
118 }
119 }
120
121 pub const fn is_host_net(&self) -> bool {
124 match self {
125 IpNet::V4(inner) => inner.is_host_net(),
126 IpNet::V6(inner) => inner.is_host_net(),
127 }
128 }
129
130 pub fn is_network_address(&self) -> bool {
133 match self {
134 IpNet::V4(inner) => inner.is_network_address(),
135 IpNet::V6(inner) => inner.is_network_address(),
136 }
137 }
138
139 pub const fn is_multicast(&self) -> bool {
141 match self {
142 IpNet::V4(inner) => inner.is_multicast(),
143 IpNet::V6(inner) => inner.is_multicast(),
144 }
145 }
146
147 pub const fn is_admin_scoped_multicast(&self) -> bool {
164 match self {
165 IpNet::V4(inner) => inner.is_admin_scoped_multicast(),
166 IpNet::V6(inner) => inner.is_admin_scoped_multicast(),
167 }
168 }
169
170 pub const fn is_admin_local_multicast(&self) -> bool {
178 match self {
179 IpNet::V4(_inner) => false,
180 IpNet::V6(inner) => inner.is_admin_local_multicast(),
181 }
182 }
183
184 pub const fn is_local_multicast(&self) -> bool {
190 match self {
191 IpNet::V4(inner) => inner.is_local_multicast(),
192 IpNet::V6(_inner) => false,
193 }
194 }
195
196 pub const fn is_site_local_multicast(&self) -> bool {
203 match self {
204 IpNet::V4(_inner) => false,
205 IpNet::V6(inner) => inner.is_site_local_multicast(),
206 }
207 }
208
209 pub const fn is_org_local_multicast(&self) -> bool {
219 match self {
220 IpNet::V4(inner) => inner.is_org_local_multicast(),
221 IpNet::V6(inner) => inner.is_org_local_multicast(),
222 }
223 }
224
225 pub const fn is_unique_local(&self) -> bool {
228 match self {
229 IpNet::V4(_inner) => false, IpNet::V6(inner) => inner.is_unique_local(),
231 }
232 }
233
234 pub const fn is_loopback(&self) -> bool {
236 match self {
237 IpNet::V4(inner) => inner.is_loopback(),
238 IpNet::V6(inner) => inner.is_loopback(),
239 }
240 }
241
242 pub fn contains(&self, addr: IpAddr) -> bool {
247 match (self, addr) {
248 (IpNet::V4(net), IpAddr::V4(ip)) => net.contains(ip),
249 (IpNet::V6(net), IpAddr::V6(ip)) => net.contains(ip),
250 (_, _) => false,
251 }
252 }
253
254 pub fn is_subnet_of(&self, other: &Self) -> bool {
259 match (self, other) {
260 (IpNet::V4(net), IpNet::V4(other)) => net.is_subnet_of(other),
261 (IpNet::V6(net), IpNet::V6(other)) => net.is_subnet_of(other),
262 (_, _) => false,
263 }
264 }
265
266 pub fn is_supernet_of(&self, other: &Self) -> bool {
271 other.is_subnet_of(self)
272 }
273
274 pub fn overlaps(&self, other: &Self) -> bool {
279 match (self, other) {
280 (IpNet::V4(net), IpNet::V4(other)) => net.overlaps(other),
281 (IpNet::V6(net), IpNet::V6(other)) => net.overlaps(other),
282 (_, _) => false,
283 }
284 }
285
286 pub const fn is_ipv4(&self) -> bool {
288 matches!(self, IpNet::V4(_))
289 }
290
291 pub const fn is_ipv6(&self) -> bool {
293 matches!(self, IpNet::V6(_))
294 }
295}
296
297impl From<Ipv4Net> for IpNet {
298 fn from(n: Ipv4Net) -> IpNet {
299 IpNet::V4(n)
300 }
301}
302
303impl From<Ipv6Net> for IpNet {
304 fn from(n: Ipv6Net) -> IpNet {
305 IpNet::V6(n)
306 }
307}
308
309impl std::fmt::Display for IpNet {
310 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
311 match self {
312 IpNet::V4(inner) => write!(f, "{inner}"),
313 IpNet::V6(inner) => write!(f, "{inner}"),
314 }
315 }
316}
317
318impl std::str::FromStr for IpNet {
319 type Err = IpNetParseError;
320
321 fn from_str(s: &str) -> Result<Self, Self::Err> {
322 let Some((addr_str, prefix_str)) = s.split_once('/') else {
323 return Err(IpNetParseError::NoPrefix);
324 };
325
326 let prefix = prefix_str.parse().map_err(IpNetParseError::InvalidPrefix)?;
327 let addr = addr_str.parse().map_err(IpNetParseError::InvalidAddr)?;
328 IpNet::new(addr, prefix).map_err(IpNetParseError::PrefixValue)
329 }
330}
331
332#[cfg(feature = "schemars")]
333impl schemars::JsonSchema for IpNet {
334 fn schema_name() -> String {
335 "IpNet".to_string()
336 }
337
338 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
339 use crate::schema_util::label_schema;
340 schemars::schema::SchemaObject {
341 subschemas: Some(Box::new(schemars::schema::SubschemaValidation {
342 one_of: Some(vec![
343 label_schema("v4", gen.subschema_for::<Ipv4Net>()),
344 label_schema("v6", gen.subschema_for::<Ipv6Net>()),
345 ]),
346 ..Default::default()
347 })),
348 extensions: crate::schema_util::extension("IpNet", "0.1.0"),
349 ..Default::default()
350 }
351 .into()
352 }
353}
354
355pub const IPV4_NET_WIDTH_MAX: u8 = 32;
357
358#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
360pub struct Ipv4Net {
361 addr: Ipv4Addr,
362 width: u8,
363}
364
365impl Ipv4Net {
366 pub fn new(addr: Ipv4Addr, width: u8) -> Result<Self, IpNetPrefixError> {
368 if width > IPV4_NET_WIDTH_MAX {
369 Err(IpNetPrefixError(width))
370 } else {
371 Ok(Self { addr, width })
372 }
373 }
374
375 pub const fn new_unchecked(addr: Ipv4Addr, width: u8) -> Self {
378 Self { addr, width }
379 }
380
381 pub const fn host_net(addr: Ipv4Addr) -> Self {
383 Self {
384 addr,
385 width: IPV4_NET_WIDTH_MAX,
386 }
387 }
388
389 pub const fn addr(&self) -> Ipv4Addr {
391 self.addr
392 }
393
394 pub const fn width(&self) -> u8 {
396 self.width
397 }
398
399 pub(crate) fn mask(&self) -> u32 {
400 Self::mask_for_width(self.width)
401 }
402
403 pub(crate) fn mask_for_width(width: u8) -> u32 {
404 u32::MAX
405 .checked_shl((IPV4_NET_WIDTH_MAX - width) as u32)
406 .unwrap_or(0)
407 }
408
409 pub fn mask_addr(&self) -> Ipv4Addr {
411 Ipv4Addr::from(self.mask())
412 }
413
414 pub const fn is_host_net(&self) -> bool {
417 self.width == IPV4_NET_WIDTH_MAX
418 }
419
420 pub fn is_network_address(&self) -> bool {
423 self.addr == self.prefix()
424 }
425
426 pub const fn is_multicast(&self) -> bool {
428 self.addr.is_multicast()
429 }
430
431 pub const fn is_admin_scoped_multicast(&self) -> bool {
440 self.addr.octets()[0] == 239
444 }
445
446 pub const fn is_local_multicast(&self) -> bool {
452 let octets = self.addr.octets();
454 octets[0] == 239 && octets[1] == 255
455 }
456
457 pub const fn is_org_local_multicast(&self) -> bool {
462 let octets = self.addr.octets();
465 octets[0] == 239 && (octets[1] >= 192 && octets[1] <= 195)
466 }
467
468 pub const fn is_loopback(&self) -> bool {
470 self.addr.is_loopback()
471 }
472
473 pub const fn size(&self) -> Option<u32> {
477 1u32.checked_shl((IPV4_NET_WIDTH_MAX - self.width) as u32)
478 }
479
480 pub fn prefix(&self) -> Ipv4Addr {
482 self.first_addr()
483 }
484
485 pub fn network(&self) -> Option<Ipv4Addr> {
488 (self.width < 31).then(|| self.first_addr())
489 }
490
491 pub fn broadcast(&self) -> Option<Ipv4Addr> {
494 (self.width < 31).then(|| self.last_addr())
495 }
496
497 pub fn first_addr(&self) -> Ipv4Addr {
499 let addr: u32 = self.addr.into();
500 Ipv4Addr::from(addr & self.mask())
501 }
502
503 pub fn last_addr(&self) -> Ipv4Addr {
505 let addr: u32 = self.addr.into();
506 Ipv4Addr::from(addr | !self.mask())
507 }
508
509 pub fn first_host(&self) -> Ipv4Addr {
513 let mask = self.mask();
514 let addr: u32 = self.addr.into();
515 let first = addr & mask;
516 if self.width == 31 || self.width == 32 {
517 Ipv4Addr::from(first)
518 } else {
519 Ipv4Addr::from(first + 1)
520 }
521 }
522
523 pub fn last_host(&self) -> Ipv4Addr {
528 let mask = self.mask();
529 let addr: u32 = self.addr.into();
530 let last = addr | !mask;
531 if self.width == 31 || self.width == 32 {
532 Ipv4Addr::from(last)
533 } else {
534 Ipv4Addr::from(last - 1)
535 }
536 }
537
538 pub fn contains(&self, other: Ipv4Addr) -> bool {
540 let mask = self.mask();
541 let addr: u32 = self.addr.into();
542 let other: u32 = other.into();
543
544 (addr & mask) == (other & mask)
545 }
546
547 pub fn nth(&self, n: usize) -> Option<Ipv4Addr> {
550 let addr: u32 = self.addr.into();
551 let nth = addr.checked_add(n.try_into().ok()?)?;
552 (nth <= self.last_addr().into()).then_some(nth.into())
553 }
554
555 pub fn addr_iter(&self) -> impl Iterator<Item = Ipv4Addr> {
557 Ipv4NetIter {
558 next: Some(self.first_addr().into()),
559 last: self.last_addr().into(),
560 }
561 }
562
563 pub fn host_iter(&self) -> impl Iterator<Item = Ipv4Addr> {
567 Ipv4NetIter {
568 next: Some(self.first_host().into()),
569 last: self.last_host().into(),
570 }
571 }
572
573 pub fn is_subnet_of(&self, other: &Self) -> bool {
575 other.first_addr() <= self.first_addr() && other.last_addr() >= self.last_addr()
576 }
577
578 pub fn is_supernet_of(&self, other: &Self) -> bool {
580 other.is_subnet_of(self)
581 }
582
583 pub fn overlaps(&self, other: &Self) -> bool {
586 let (parent, child) = if self.width <= other.width {
587 (self, other)
588 } else {
589 (other, self)
590 };
591
592 child.is_subnet_of(parent)
593 }
594
595 pub fn resize(&self, width: u8, fill: u32) -> Result<Self, IpNetPrefixError> {
629 if width > IPV4_NET_WIDTH_MAX {
630 return Err(IpNetPrefixError(width));
631 }
632 if width < self.width {
633 Ok(Self {
634 addr: Ipv4Addr::from(u32::from(self.addr) & Self::mask_for_width(width)),
635 width,
636 })
637 } else if width == self.width {
638 Ok(*self)
639 } else {
640 let fill = (fill << (IPV4_NET_WIDTH_MAX - width)) & Self::mask_for_width(width);
641 Ok(Self {
642 addr: Ipv4Addr::from(u32::from(self.addr) | fill),
643 width,
644 })
645 }
646 }
647}
648
649impl std::fmt::Display for Ipv4Net {
650 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
651 write!(f, "{}/{}", &self.addr, self.width)
652 }
653}
654
655impl std::str::FromStr for Ipv4Net {
656 type Err = IpNetParseError;
657
658 fn from_str(s: &str) -> Result<Self, Self::Err> {
659 let Some((addr_str, prefix_str)) = s.split_once('/') else {
660 return Err(IpNetParseError::NoPrefix);
661 };
662
663 let prefix = prefix_str.parse().map_err(IpNetParseError::InvalidPrefix)?;
664 let addr = addr_str.parse().map_err(IpNetParseError::InvalidAddr)?;
665 Ipv4Net::new(addr, prefix).map_err(IpNetParseError::PrefixValue)
666 }
667}
668
669#[cfg(feature = "serde")]
670impl<'de> serde::Deserialize<'de> for Ipv4Net {
671 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
672 where
673 D: serde::Deserializer<'de>,
674 {
675 String::deserialize(deserializer)?
676 .parse()
677 .map_err(<D::Error as serde::de::Error>::custom)
678 }
679}
680
681#[cfg(feature = "serde")]
682impl serde::Serialize for Ipv4Net {
683 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
684 where
685 S: serde::Serializer,
686 {
687 serializer.serialize_str(&format!("{self}"))
688 }
689}
690
691#[cfg(feature = "schemars")]
692const IPV4_NET_REGEX: &str = concat!(
693 r#"^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}"#,
694 r#"([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"#,
695 r#"/([0-9]|1[0-9]|2[0-9]|3[0-2])$"#,
696);
697
698#[cfg(feature = "schemars")]
699impl schemars::JsonSchema for Ipv4Net {
700 fn schema_name() -> String {
701 "Ipv4Net".to_string()
702 }
703
704 fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
705 schemars::schema::SchemaObject {
706 metadata: Some(Box::new(schemars::schema::Metadata {
707 title: Some("An IPv4 subnet".to_string()),
708 description: Some("An IPv4 subnet, including prefix and prefix length".to_string()),
709 examples: vec!["192.168.1.0/24".into()],
710 ..Default::default()
711 })),
712 instance_type: Some(schemars::schema::InstanceType::String.into()),
713 string: Some(Box::new(schemars::schema::StringValidation {
714 pattern: Some(IPV4_NET_REGEX.to_string()),
715 ..Default::default()
716 })),
717 extensions: crate::schema_util::extension("Ipv4Net", "0.1.0"),
718 ..Default::default()
719 }
720 .into()
721 }
722}
723
724pub const IPV6_NET_WIDTH_MAX: u8 = 128;
726
727#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
732#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
733pub enum MulticastScopeV6 {
734 InterfaceLocal = 0x1,
736 LinkLocal = 0x2,
738 AdminLocal = 0x4,
740 SiteLocal = 0x5,
742 OrganizationLocal = 0x8,
744 Global = 0xE,
746}
747
748impl MulticastScopeV6 {
749 pub const fn is_admin_scoped_multicast(&self) -> bool {
752 matches!(
753 self,
754 MulticastScopeV6::AdminLocal
755 | MulticastScopeV6::SiteLocal
756 | MulticastScopeV6::OrganizationLocal
757 )
758 }
759
760 pub const fn from_u8(scope: u8) -> Option<Self> {
763 match scope {
764 0x1 => Some(MulticastScopeV6::InterfaceLocal),
765 0x2 => Some(MulticastScopeV6::LinkLocal),
766 0x4 => Some(MulticastScopeV6::AdminLocal),
767 0x5 => Some(MulticastScopeV6::SiteLocal),
768 0x8 => Some(MulticastScopeV6::OrganizationLocal),
769 0xE => Some(MulticastScopeV6::Global),
770 _ => None,
771 }
772 }
773}
774
775#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
777pub struct Ipv6Net {
778 addr: Ipv6Addr,
779 width: u8,
780}
781
782impl Ipv6Net {
783 pub fn new(addr: Ipv6Addr, width: u8) -> Result<Self, IpNetPrefixError> {
785 if width > IPV6_NET_WIDTH_MAX {
786 Err(IpNetPrefixError(width))
787 } else {
788 Ok(Self { addr, width })
789 }
790 }
791
792 pub const fn new_unchecked(addr: Ipv6Addr, width: u8) -> Self {
795 Self { addr, width }
796 }
797
798 pub const fn host_net(addr: Ipv6Addr) -> Self {
800 Self {
801 addr,
802 width: IPV6_NET_WIDTH_MAX,
803 }
804 }
805
806 pub const fn addr(&self) -> Ipv6Addr {
808 self.addr
809 }
810
811 pub const fn width(&self) -> u8 {
813 self.width
814 }
815
816 pub(crate) fn mask(&self) -> u128 {
817 Self::mask_for_width(self.width)
818 }
819
820 pub(crate) fn mask_for_width(width: u8) -> u128 {
821 u128::MAX
822 .checked_shl((IPV6_NET_WIDTH_MAX - width) as u32)
823 .unwrap_or(0)
824 }
825
826 pub fn mask_addr(&self) -> Ipv6Addr {
828 Ipv6Addr::from(self.mask())
829 }
830
831 pub const fn is_host_net(&self) -> bool {
834 self.width == IPV6_NET_WIDTH_MAX
835 }
836
837 pub fn is_network_address(&self) -> bool {
840 self.addr == self.prefix()
841 }
842
843 pub const fn is_multicast(&self) -> bool {
845 self.addr.is_multicast()
846 }
847
848 pub const fn multicast_scope(&self) -> Option<MulticastScopeV6> {
855 if !self.addr.is_multicast() {
856 return None;
857 }
858
859 let segments = self.addr.segments();
861 let scope = (segments[0] & 0x000F) as u8;
862
863 MulticastScopeV6::from_u8(scope)
864 }
865
866 pub const fn is_admin_scoped_multicast(&self) -> bool {
880 match self.multicast_scope() {
881 Some(scope) => scope.is_admin_scoped_multicast(),
882 None => false,
883 }
884 }
885
886 pub const fn is_admin_local_multicast(&self) -> bool {
892 matches!(self.multicast_scope(), Some(MulticastScopeV6::AdminLocal))
893 }
894
895 pub const fn is_site_local_multicast(&self) -> bool {
901 matches!(self.multicast_scope(), Some(MulticastScopeV6::SiteLocal))
902 }
903
904 pub const fn is_org_local_multicast(&self) -> bool {
910 matches!(
911 self.multicast_scope(),
912 Some(MulticastScopeV6::OrganizationLocal)
913 )
914 }
915
916 pub const fn is_loopback(&self) -> bool {
918 self.addr.is_loopback()
919 }
920
921 pub const fn size(&self) -> Option<u128> {
925 1u128.checked_shl((IPV6_NET_WIDTH_MAX - self.width) as u32)
926 }
927
928 pub fn prefix(&self) -> Ipv6Addr {
930 self.first_addr()
931 }
932
933 pub const fn is_unique_local(&self) -> bool {
938 self.addr.is_unique_local()
939 }
940
941 pub fn first_addr(&self) -> Ipv6Addr {
943 let addr: u128 = self.addr.into();
944 Ipv6Addr::from(addr & self.mask())
945 }
946
947 pub fn last_addr(&self) -> Ipv6Addr {
949 let addr: u128 = self.addr.into();
950 Ipv6Addr::from(addr | !self.mask())
951 }
952
953 pub fn iter(&self) -> impl Iterator<Item = Ipv6Addr> {
955 Ipv6NetIter {
956 next: Some(self.first_addr().into()),
957 last: self.last_addr().into(),
958 }
959 }
960
961 pub fn contains(&self, other: Ipv6Addr) -> bool {
963 let mask = self.mask();
964 let addr: u128 = self.addr.into();
965 let other: u128 = other.into();
966
967 (addr & mask) == (other & mask)
968 }
969
970 pub fn nth(&self, n: u128) -> Option<Ipv6Addr> {
973 let addr: u128 = self.addr.into();
974 let nth = addr.checked_add(n)?;
975 (nth <= self.last_addr().into()).then_some(nth.into())
976 }
977
978 pub fn is_subnet_of(&self, other: &Self) -> bool {
980 other.first_addr() <= self.first_addr() && other.last_addr() >= self.last_addr()
981 }
982
983 pub fn is_supernet_of(&self, other: &Self) -> bool {
985 other.is_subnet_of(self)
986 }
987
988 pub fn overlaps(&self, other: &Self) -> bool {
991 let (parent, child) = if self.width <= other.width {
992 (self, other)
993 } else {
994 (other, self)
995 };
996
997 child.is_subnet_of(parent)
998 }
999
1000 pub fn resize(&self, width: u8, fill: u128) -> Result<Self, IpNetPrefixError> {
1033 if width > IPV6_NET_WIDTH_MAX {
1034 return Err(IpNetPrefixError(width));
1035 }
1036 if width < self.width {
1037 Ok(Self {
1038 addr: Ipv6Addr::from(u128::from(self.addr) & Self::mask_for_width(width)),
1039 width,
1040 })
1041 } else if width == self.width {
1042 Ok(*self)
1043 } else {
1044 let fill = (fill << (IPV6_NET_WIDTH_MAX - width)) & Self::mask_for_width(width);
1045 Ok(Self {
1046 addr: Ipv6Addr::from(u128::from(self.addr) | fill),
1047 width,
1048 })
1049 }
1050 }
1051}
1052
1053impl std::fmt::Display for Ipv6Net {
1054 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1055 write!(f, "{}/{}", &self.addr, self.width)
1056 }
1057}
1058
1059impl std::str::FromStr for Ipv6Net {
1060 type Err = IpNetParseError;
1061
1062 fn from_str(s: &str) -> Result<Self, Self::Err> {
1063 let Some((addr_str, prefix_str)) = s.split_once('/') else {
1064 return Err(IpNetParseError::NoPrefix);
1065 };
1066
1067 let prefix = prefix_str.parse().map_err(IpNetParseError::InvalidPrefix)?;
1068 let addr = addr_str.parse().map_err(IpNetParseError::InvalidAddr)?;
1069 Ipv6Net::new(addr, prefix).map_err(IpNetParseError::PrefixValue)
1070 }
1071}
1072
1073#[cfg(feature = "serde")]
1074impl<'de> serde::Deserialize<'de> for Ipv6Net {
1075 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1076 where
1077 D: serde::Deserializer<'de>,
1078 {
1079 String::deserialize(deserializer)?
1080 .parse()
1081 .map_err(<D::Error as serde::de::Error>::custom)
1082 }
1083}
1084
1085#[cfg(feature = "serde")]
1086impl serde::Serialize for Ipv6Net {
1087 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1088 where
1089 S: serde::Serializer,
1090 {
1091 serializer.serialize_str(&format!("{self}"))
1092 }
1093}
1094
1095#[cfg(feature = "schemars")]
1096const IPV6_NET_REGEX: &str = concat!(
1097 r#"^("#,
1098 r#"([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|"#,
1099 r#"([0-9a-fA-F]{1,4}:){1,7}:|"#,
1100 r#"([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|"#,
1101 r#"([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|"#,
1102 r#"([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|"#,
1103 r#"([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|"#,
1104 r#"([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|"#,
1105 r#"[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|"#,
1106 r#":((:[0-9a-fA-F]{1,4}){1,7}|:)|"#,
1107 r#"fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|"#,
1108 r#"::(ffff(:0{1,4}){0,1}:){0,1}"#,
1109 r#"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}"#,
1110 r#"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|"#,
1111 r#"([0-9a-fA-F]{1,4}:){1,4}:"#,
1112 r#"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}"#,
1113 r#"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"#,
1114 r#")\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$"#,
1115);
1116
1117#[cfg(feature = "schemars")]
1118impl schemars::JsonSchema for Ipv6Net {
1119 fn schema_name() -> String {
1120 "Ipv6Net".to_string()
1121 }
1122
1123 fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1124 schemars::schema::SchemaObject {
1125 metadata: Some(Box::new(schemars::schema::Metadata {
1126 title: Some("An IPv6 subnet".to_string()),
1127 description: Some("An IPv6 subnet, including prefix and subnet mask".to_string()),
1128 examples: vec!["fd12:3456::/64".into()],
1129 ..Default::default()
1130 })),
1131 instance_type: Some(schemars::schema::InstanceType::String.into()),
1132 string: Some(Box::new(schemars::schema::StringValidation {
1133 pattern: Some(IPV6_NET_REGEX.to_string()),
1134 ..Default::default()
1135 })),
1136 extensions: crate::schema_util::extension("Ipv6Net", "0.1.0"),
1137 ..Default::default()
1138 }
1139 .into()
1140 }
1141}
1142
1143pub struct Ipv4NetIter {
1144 next: Option<u32>,
1145 last: u32,
1146}
1147
1148impl Iterator for Ipv4NetIter {
1149 type Item = Ipv4Addr;
1150
1151 fn next(&mut self) -> Option<Self::Item> {
1152 let next = self.next?;
1153 if next == self.last {
1154 self.next = None;
1155 } else {
1156 self.next = Some(next + 1)
1157 }
1158 Some(next.into())
1159 }
1160
1161 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1162 let next = self.next?;
1163 let nth = next.checked_add(n as u32)?;
1164 self.next = (nth <= self.last).then_some(nth);
1165 self.next()
1166 }
1167}
1168
1169pub struct Ipv6NetIter {
1170 next: Option<u128>,
1171 last: u128,
1172}
1173
1174impl Iterator for Ipv6NetIter {
1175 type Item = Ipv6Addr;
1176
1177 fn next(&mut self) -> Option<Self::Item> {
1178 let next = self.next?;
1179 if next == self.last {
1180 self.next = None;
1181 } else {
1182 self.next = Some(next + 1)
1183 }
1184 Some(next.into())
1185 }
1186
1187 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1188 let next = self.next?;
1189 let nth = next.checked_add(n as u128)?;
1190 self.next = (nth <= self.last).then_some(nth);
1191 self.next()
1192 }
1193}
1194
1195#[cfg(feature = "ula")]
1197#[derive(Debug, Clone)]
1198pub enum UlaBuildError {
1199 Time(SystemTimeError),
1201 Prefix(IpNetPrefixError),
1203}
1204
1205#[cfg(feature = "ula")]
1206impl std::fmt::Display for UlaBuildError {
1207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1208 match self {
1209 Self::Time(e) => write!(f, "invalid time provided: {e}"),
1210 Self::Prefix(e) => write!(f, "unable to construct ULA prefix: {e}"),
1211 }
1212 }
1213}
1214
1215#[cfg(feature = "ula")]
1216impl std::error::Error for UlaBuildError {}
1217
1218#[cfg(feature = "ula")]
1219impl From<SystemTimeError> for UlaBuildError {
1220 fn from(value: SystemTimeError) -> Self {
1221 Self::Time(value)
1222 }
1223}
1224
1225#[cfg(feature = "ula")]
1226impl From<IpNetPrefixError> for UlaBuildError {
1227 fn from(value: IpNetPrefixError) -> Self {
1228 Self::Prefix(value)
1229 }
1230}
1231
1232#[cfg(feature = "ula")]
1234#[derive(Default)]
1235pub struct UlaBuilder {
1236 date: Option<SystemTime>,
1237 id: Option<Vec<u8>>,
1238}
1239
1240#[cfg(feature = "ula")]
1241impl UlaBuilder {
1242 pub fn id(&mut self, id: impl AsRef<[u8]>) -> &mut Self {
1244 self.id = Some(id.as_ref().to_vec());
1245 self
1246 }
1247
1248 pub fn date(&mut self, date: SystemTime) -> &mut Self {
1250 self.date = Some(date);
1251 self
1252 }
1253
1254 pub fn build(&self) -> Result<Ipv6Net, UlaBuildError> {
1261 use sha1::{Digest, Sha1};
1262 use std::time::SystemTime;
1263
1264 let id: Vec<u8> = self.id.clone().unwrap_or_else(|| {
1266 let mut rng = rand::rng();
1267 rng.random::<[u8; 8]>().to_vec()
1268 });
1269
1270 let time = self.date.unwrap_or_else(SystemTime::now);
1272 let ntp_time = system_time_to_ntp(time)?;
1273
1274 let mut hasher = Sha1::new();
1276 hasher.update(ntp_time.to_be_bytes());
1277 hasher.update(&id);
1278 let hash = hasher.finalize();
1279
1280 let global_id = &hash[..5];
1282
1283 let addr = Ipv6Addr::new(
1286 0xfd00 | (global_id[0] as u16),
1287 u16::from_be_bytes([global_id[1], global_id[2]]),
1288 u16::from_be_bytes([global_id[3], global_id[4]]),
1289 0,
1290 0,
1291 0,
1292 0,
1293 0,
1294 );
1295
1296 Ok(Ipv6Net::new(addr, 48)?)
1297 }
1298}
1299
1300#[cfg(feature = "ula")]
1301fn system_time_to_ntp(time: SystemTime) -> Result<u64, SystemTimeError> {
1302 use std::time::UNIX_EPOCH;
1303
1304 const NTP_UNIX_OFFSET: u64 = 2208988800;
1308
1309 let duration = time.duration_since(UNIX_EPOCH)?;
1310 let secs = duration.as_secs() + NTP_UNIX_OFFSET;
1311 let frac = ((duration.subsec_nanos() as u64) << 32) / 1_000_000_000;
1312
1313 Ok((secs << 32) | frac)
1314}
1315
1316#[cfg(feature = "ipnetwork")]
1317mod ipnetwork_feature {
1318 use super::*;
1319 use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network};
1320
1321 impl From<IpNetwork> for IpNet {
1322 fn from(value: IpNetwork) -> Self {
1323 match value {
1324 IpNetwork::V4(net) => Self::V4(net.into()),
1325 IpNetwork::V6(net) => Self::V6(net.into()),
1326 }
1327 }
1328 }
1329
1330 impl From<IpNet> for IpNetwork {
1331 fn from(value: IpNet) -> Self {
1332 match value {
1333 IpNet::V4(net) => Self::V4(net.into()),
1334 IpNet::V6(net) => Self::V6(net.into()),
1335 }
1336 }
1337 }
1338
1339 impl From<Ipv4Network> for Ipv4Net {
1340 fn from(value: Ipv4Network) -> Self {
1341 Self {
1342 addr: value.ip(),
1343 width: value.prefix(),
1344 }
1345 }
1346 }
1347
1348 impl From<Ipv4Net> for Ipv4Network {
1349 fn from(value: Ipv4Net) -> Self {
1350 Self::new(value.addr, value.width).unwrap()
1351 }
1352 }
1353
1354 impl From<Ipv6Network> for Ipv6Net {
1355 fn from(value: Ipv6Network) -> Self {
1356 Self {
1357 addr: value.ip(),
1358 width: value.prefix(),
1359 }
1360 }
1361 }
1362
1363 impl From<Ipv6Net> for Ipv6Network {
1364 fn from(value: Ipv6Net) -> Self {
1365 Self::new(value.addr, value.width).unwrap()
1366 }
1367 }
1368}
1369
1370#[cfg(test)]
1371mod tests {
1372 use super::*;
1373
1374 #[test]
1375 fn test_ipv6_regex() {
1376 let re = regress::Regex::new(IPV6_NET_REGEX).unwrap();
1377 for case in [
1378 "1:2:3:4:5:6:7:8",
1379 "1:a:2:b:3:c:4:d",
1380 "1::",
1381 "::1",
1382 "::",
1383 "1::3:4:5:6:7:8",
1384 "1:2::4:5:6:7:8",
1385 "1:2:3::5:6:7:8",
1386 "1:2:3:4::6:7:8",
1387 "1:2:3:4:5::7:8",
1388 "1:2:3:4:5:6::8",
1389 "1:2:3:4:5:6:7::",
1390 "2001::",
1391 "fd00::",
1392 "::100:1",
1393 "fd12:3456::",
1394 ] {
1395 for prefix in 0..=128 {
1396 let net = format!("{case}/{prefix}");
1397 assert!(
1398 re.find(&net).is_some(),
1399 "Expected to match IPv6 case: {prefix}",
1400 );
1401 }
1402 }
1403 }
1404
1405 #[test]
1406 fn test_ipv4_net_operations() {
1407 let x: IpNet = "0.0.0.0/0".parse().unwrap();
1408 assert_eq!(x, IpNet::V4("0.0.0.0/0".parse().unwrap()));
1409 }
1410
1411 #[test]
1412 fn test_ipnet_serde() {
1413 let net_str = "fd00:2::/32";
1414 let net: IpNet = net_str.parse().unwrap();
1415 let ser = serde_json::to_string(&net).unwrap();
1416
1417 assert_eq!(format!(r#""{net_str}""#), ser);
1418 let net_des = serde_json::from_str::<IpNet>(&ser).unwrap();
1419 assert_eq!(net, net_des);
1420
1421 let net_str = "fd00:47::1/64";
1422 let net: IpNet = net_str.parse().unwrap();
1423 let ser = serde_json::to_string(&net).unwrap();
1424
1425 assert_eq!(format!(r#""{net_str}""#), ser);
1426 let net_des = serde_json::from_str::<IpNet>(&ser).unwrap();
1427 assert_eq!(net, net_des);
1428
1429 let net_str = "192.168.1.1/16";
1430 let net: IpNet = net_str.parse().unwrap();
1431 let ser = serde_json::to_string(&net).unwrap();
1432
1433 assert_eq!(format!(r#""{net_str}""#), ser);
1434 let net_des = serde_json::from_str::<IpNet>(&ser).unwrap();
1435 assert_eq!(net, net_des);
1436
1437 let net_str = "0.0.0.0/0";
1438 let net: IpNet = net_str.parse().unwrap();
1439 let ser = serde_json::to_string(&net).unwrap();
1440
1441 assert_eq!(format!(r#""{net_str}""#), ser);
1442 let net_des = serde_json::from_str::<IpNet>(&ser).unwrap();
1443 assert_eq!(net, net_des);
1444 }
1445
1446 #[test]
1447 fn test_ipnet_size() {
1448 let net = Ipv4Net::host_net("1.2.3.4".parse().unwrap());
1449 assert_eq!(net.size(), Some(1));
1450 assert_eq!(net.width(), 32);
1451 assert_eq!(net.mask(), 0xffff_ffff);
1452 assert_eq!(net.mask_addr(), Ipv4Addr::new(0xff, 0xff, 0xff, 0xff));
1453
1454 let net = Ipv4Net::new("1.2.3.4".parse().unwrap(), 24).unwrap();
1455 assert_eq!(net.size(), Some(256));
1456 assert_eq!(net.width(), 24);
1457 assert_eq!(net.mask(), 0xffff_ff00);
1458 assert_eq!(net.mask_addr(), Ipv4Addr::new(0xff, 0xff, 0xff, 0));
1459
1460 let net = Ipv4Net::new("0.0.0.0".parse().unwrap(), 0).unwrap();
1461 assert_eq!(net.size(), None);
1462 assert_eq!(net.width(), 0);
1463 assert_eq!(net.mask(), 0);
1464 assert_eq!(net.mask_addr(), Ipv4Addr::new(0, 0, 0, 0));
1465
1466 let net = Ipv6Net::host_net("fd00:47::1".parse().unwrap());
1467 assert_eq!(net.size(), Some(1));
1468 assert_eq!(net.width(), 128);
1469 assert_eq!(net.mask(), 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff);
1470 assert_eq!(
1471 net.mask_addr(),
1472 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff)
1473 );
1474
1475 let net = Ipv6Net::new("fd00:47::1".parse().unwrap(), 56).unwrap();
1476 assert_eq!(net.size(), Some(0x0000_0000_0000_0100_0000_0000_0000_0000));
1477 assert_eq!(net.width(), 56);
1478 assert_eq!(net.mask(), 0xffff_ffff_ffff_ff00_0000_0000_0000_0000);
1479 assert_eq!(
1480 net.mask_addr(),
1481 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xff00, 0, 0, 0, 0)
1482 );
1483 }
1484
1485 #[test]
1486 fn test_iter() {
1487 let ipnet = Ipv4Net::new(Ipv4Addr::new(0, 0, 0, 0), 0).unwrap();
1488
1489 let actual = ipnet.addr_iter().take(5).collect::<Vec<_>>();
1490 let expected = (0..5).map(Ipv4Addr::from).collect::<Vec<_>>();
1491 assert_eq!(actual, expected);
1492
1493 let actual = ipnet.addr_iter().skip(5).take(10).collect::<Vec<_>>();
1494 let expected = (5..15).map(Ipv4Addr::from).collect::<Vec<_>>();
1495 assert_eq!(actual, expected);
1496
1497 let ipnet = Ipv6Net::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0).unwrap();
1498
1499 let actual = ipnet.iter().take(5).collect::<Vec<_>>();
1500 let expected = (0..5).map(Ipv6Addr::from).collect::<Vec<_>>();
1501 assert_eq!(actual, expected);
1502
1503 let actual = ipnet.iter().skip(5).take(10).collect::<Vec<_>>();
1504 let expected = (5..15).map(Ipv6Addr::from).collect::<Vec<_>>();
1505 assert_eq!(actual, expected);
1506 }
1507
1508 #[test]
1509 fn test_contains() {
1510 let default_v4: IpNet = "0.0.0.0/0".parse().unwrap();
1511 let private_v4: IpNet = "10.0.0.0/8".parse().unwrap();
1512 let privater_v4_c0: IpNet = "10.0.0.0/9".parse().unwrap();
1513 let privater_v4_c1: IpNet = "10.128.0.0/9".parse().unwrap();
1514
1515 assert!(private_v4.is_subnet_of(&default_v4));
1516 assert!(privater_v4_c0.is_subnet_of(&default_v4));
1517 assert!(privater_v4_c0.is_subnet_of(&private_v4));
1518 assert!(privater_v4_c1.is_subnet_of(&default_v4));
1519 assert!(privater_v4_c1.is_subnet_of(&private_v4));
1520
1521 assert!(private_v4.is_supernet_of(&privater_v4_c0));
1522 assert!(private_v4.is_supernet_of(&privater_v4_c1));
1523
1524 assert!(!privater_v4_c0.overlaps(&privater_v4_c1));
1525 assert!(!privater_v4_c1.overlaps(&privater_v4_c0));
1526 assert!(privater_v4_c0.overlaps(&privater_v4_c0));
1527 assert!(privater_v4_c0.overlaps(&private_v4));
1528 assert!(private_v4.overlaps(&privater_v4_c0));
1529
1530 let child_ip: IpNet = "10.128.20.20/16".parse().unwrap();
1531 assert!(child_ip.is_subnet_of(&privater_v4_c1));
1532 assert!(!child_ip.is_subnet_of(&privater_v4_c0));
1533 }
1534
1535 #[test]
1536 fn test_is_network_addr() {
1537 let v4_net: IpNet = "127.0.0.0/8".parse().unwrap();
1538 let v4_host: IpNet = "127.0.0.1/8".parse().unwrap();
1539 let v6_net: IpNet = "fd00:1234:5678::/48".parse().unwrap();
1540 let v6_host: IpNet = "fd00:1234:5678::7777/48".parse().unwrap();
1541
1542 assert!(v4_net.is_network_address());
1543 assert!(!v4_host.is_network_address());
1544 assert!(v6_net.is_network_address());
1545 assert!(!v6_host.is_network_address());
1546
1547 let two_addr: IpNet = "10.7.7.64/31".parse().unwrap();
1550 let one_addr: IpNet = "10.7.7.64/32".parse().unwrap();
1551 assert!(two_addr.is_network_address());
1552 assert!(one_addr.is_network_address());
1553
1554 let unspec: IpNet = "0.0.0.0/0".parse().unwrap();
1557 assert!(unspec.is_network_address());
1558 }
1559
1560 #[test]
1561 fn test_is_multicast_with_scopes() {
1562 let v4_mcast: IpNet = "224.0.0.1/32".parse().unwrap();
1564 let v4_not_mcast: IpNet = "192.168.1.1/24".parse().unwrap();
1565
1566 assert!(v4_mcast.is_multicast());
1567 assert!(!v4_not_mcast.is_multicast());
1568
1569 let v6_mcast: IpNet = "ff02::1/128".parse().unwrap();
1571 let v6_not_mcast: IpNet = "2001:db8::1/64".parse().unwrap();
1572
1573 assert!(v6_mcast.is_multicast());
1574 assert!(!v6_not_mcast.is_multicast());
1575
1576 let v6_site_local_mcast: IpNet = "ff05::1/128".parse().unwrap();
1578 let v6_org_local_mcast: IpNet = "ff08::1/128".parse().unwrap();
1580 let v6_admin_local_mcast: IpNet = "ff04::1/128".parse().unwrap();
1582 let v6_link_local_mcast: IpNet = "ff02::1/128".parse().unwrap();
1584
1585 assert!(v6_admin_local_mcast.is_admin_scoped_multicast());
1587 assert!(v6_site_local_mcast.is_admin_scoped_multicast());
1588 assert!(v6_org_local_mcast.is_admin_scoped_multicast());
1589 assert!(!v6_link_local_mcast.is_admin_scoped_multicast()); assert!(!v6_not_mcast.is_admin_scoped_multicast());
1591
1592 let v4_admin_scoped: IpNet = "239.0.0.1/32".parse().unwrap();
1594 let v4_admin_scoped_range: IpNet = "239.192.0.0/16".parse().unwrap();
1595 assert!(v4_admin_scoped.is_admin_scoped_multicast());
1596 assert!(v4_admin_scoped_range.is_admin_scoped_multicast());
1597 assert!(!v4_mcast.is_admin_scoped_multicast());
1598
1599 assert!(!v6_site_local_mcast.is_admin_local_multicast());
1601 assert!(!v6_org_local_mcast.is_admin_local_multicast());
1602 assert!(v6_admin_local_mcast.is_admin_local_multicast());
1603 assert!(!v6_link_local_mcast.is_admin_local_multicast());
1604 assert!(!v6_not_mcast.is_admin_local_multicast());
1605 assert!(!v4_mcast.is_admin_local_multicast()); assert!(!v4_admin_scoped.is_admin_local_multicast()); let v4_local_mcast: IpNet = "239.255.0.1/32".parse().unwrap();
1610 let v4_local_mcast_range: IpNet = "239.255.128.0/24".parse().unwrap();
1611 let v4_not_local: IpNet = "239.254.255.255/32".parse().unwrap();
1612 assert!(v4_local_mcast.is_local_multicast());
1613 assert!(v4_local_mcast_range.is_local_multicast());
1614 assert!(!v4_not_local.is_local_multicast());
1615 assert!(!v4_mcast.is_local_multicast()); assert!(!v6_admin_local_mcast.is_local_multicast()); assert!(v6_site_local_mcast.is_site_local_multicast());
1620 assert!(!v6_org_local_mcast.is_site_local_multicast());
1621 assert!(!v6_admin_local_mcast.is_site_local_multicast());
1622 assert!(!v6_link_local_mcast.is_site_local_multicast());
1623 assert!(!v6_not_mcast.is_site_local_multicast());
1624 assert!(!v4_mcast.is_site_local_multicast());
1625
1626 assert!(!v6_site_local_mcast.is_org_local_multicast());
1629 assert!(v6_org_local_mcast.is_org_local_multicast());
1630 assert!(!v6_admin_local_mcast.is_org_local_multicast());
1631 assert!(!v6_link_local_mcast.is_org_local_multicast());
1632 assert!(!v6_not_mcast.is_org_local_multicast());
1633
1634 let v4_org_local_mcast: IpNet = "239.192.0.1/32".parse().unwrap();
1636 let v4_org_local_mcast_end: IpNet = "239.195.255.255/32".parse().unwrap();
1637 let v4_not_org_local: IpNet = "239.196.0.0/32".parse().unwrap();
1638 assert!(v4_org_local_mcast.is_org_local_multicast());
1639 assert!(v4_org_local_mcast_end.is_org_local_multicast());
1640 assert!(!v4_not_org_local.is_org_local_multicast());
1641 assert!(!v4_mcast.is_org_local_multicast()); }
1643
1644 #[test]
1645 fn test_ipv6_multicast_scope() {
1646 use MulticastScopeV6::*;
1647
1648 let link_local: Ipv6Net = "ff02::1/128".parse().unwrap();
1649 let admin_local: Ipv6Net = "ff04::1/128".parse().unwrap();
1650 let site_local: Ipv6Net = "ff05::1/128".parse().unwrap();
1651 let org_local: Ipv6Net = "ff08::1/128".parse().unwrap();
1652 let global: Ipv6Net = "ff0e::1/128".parse().unwrap();
1653 let not_mcast: Ipv6Net = "2001:db8::1/64".parse().unwrap();
1654
1655 assert_eq!(link_local.multicast_scope(), Some(LinkLocal));
1656 assert_eq!(admin_local.multicast_scope(), Some(AdminLocal));
1657 assert_eq!(site_local.multicast_scope(), Some(SiteLocal));
1658 assert_eq!(org_local.multicast_scope(), Some(OrganizationLocal));
1659 assert_eq!(global.multicast_scope(), Some(Global));
1660 assert_eq!(not_mcast.multicast_scope(), None);
1661
1662 assert!(!LinkLocal.is_admin_scoped_multicast());
1664 assert!(AdminLocal.is_admin_scoped_multicast());
1665 assert!(SiteLocal.is_admin_scoped_multicast());
1666 assert!(OrganizationLocal.is_admin_scoped_multicast());
1667 assert!(!Global.is_admin_scoped_multicast());
1668 }
1669
1670 #[cfg(feature = "ula")]
1671 #[test]
1672 fn test_ipv6_ula_builder() {
1673 let ula1 = UlaBuilder::default().build().unwrap();
1676 let ula2 = UlaBuilder::default().build().unwrap();
1677 assert_eq!(ula1.width(), 48);
1678 assert_ne!(ula1, ula2);
1679
1680 let t = SystemTime::now();
1683 let ula1 = UlaBuilder::default().date(t).build().unwrap();
1684 let ula2 = UlaBuilder::default().date(t).build().unwrap();
1685 assert_ne!(ula1, ula2);
1686
1687 let ula1 = UlaBuilder::default()
1690 .date(t)
1691 .id(vec![1, 2, 3, 4])
1692 .build()
1693 .unwrap();
1694 let ula2 = UlaBuilder::default()
1695 .date(t)
1696 .id(vec![1, 2, 3, 4])
1697 .build()
1698 .unwrap();
1699 assert_eq!(ula1, ula2);
1700 }
1701
1702 #[test]
1703 fn test_ipv6_resize() {
1704 let s56: Ipv6Net = "fd00:a:b:cc00::/56".parse().unwrap();
1705
1706 let s64 = s56.resize(64, 0xdd).unwrap();
1708 assert_eq!(s64, "fd00:a:b:ccdd::/64".parse().unwrap());
1709
1710 let s48 = s56.resize(48, 0).unwrap();
1712 assert_eq!(s48, "fd00:a:b::/48".parse().unwrap());
1713
1714 assert_eq!(s56.resize(200, 0), Result::Err(IpNetPrefixError(200)));
1716
1717 let s56: Ipv6Net = "fd00:a:b:ccdd::/56".parse().unwrap();
1719 let s64 = s56.resize(64, 0).unwrap();
1720 assert_eq!(s64, "fd00:a:b:ccdd::/64".parse().unwrap());
1721 let s64 = s56.resize(64, 0xff).unwrap();
1722 assert_eq!(s64, "fd00:a:b:ccff::/64".parse().unwrap());
1723 }
1724
1725 #[test]
1726 fn test_ipv4_resize() {
1727 let s16: Ipv4Net = "10.1.0.0/16".parse().unwrap();
1728
1729 let s24 = s16.resize(24, 2).unwrap();
1731 assert_eq!(s24, "10.1.2.0/24".parse().unwrap());
1732
1733 let s8 = s24.resize(8, 0).unwrap();
1735 assert_eq!(s8, "10.0.0.0/8".parse().unwrap());
1736
1737 assert_eq!(s16.resize(40, 0), Result::Err(IpNetPrefixError(40)));
1739
1740 let s16: Ipv4Net = "10.1.2.3/16".parse().unwrap();
1742 let s24 = s16.resize(24, 0).unwrap();
1744 assert_eq!(s24, "10.1.2.3/24".parse().unwrap());
1745 let s24 = s16.resize(24, 255).unwrap();
1746 assert_eq!(s24, "10.1.255.3/24".parse().unwrap());
1747 }
1748}