1use core::fmt::{self, Debug, Display, Formatter};
59use core::hash::Hash;
60use core::mem;
61use core::ops::{Deref, DerefMut};
62
63#[cfg(feature = "std")]
64use std::net;
65#[cfg(feature = "std")]
66use std::sync::Arc;
67
68pub use net_types_macros::GenericOverIp;
69use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
70
71use crate::{
72 LinkLocalAddr, LinkLocalAddress, MappedAddress, MulticastAddr, MulticastAddress, NonMappedAddr,
73 NonMulticastAddr, Scope, ScopeableAddress, SpecifiedAddr, SpecifiedAddress, UnicastAddr,
74 UnicastAddress, Witness, sealed,
75};
76
77#[allow(missing_docs)]
84#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
85pub enum IpVersion {
86 V4,
87 V6,
88}
89
90#[macro_export]
103macro_rules! for_any_ip_version {
104 ($ip_version:expr, $type_param:ident, $expression:expr) => {
105 match $ip_version {
106 $crate::ip::IpVersion::V4 => {
107 type $type_param = $crate::ip::Ipv4;
108 $expression
109 }
110 $crate::ip::IpVersion::V6 => {
111 type $type_param = $crate::ip::Ipv6;
112 $expression
113 }
114 }
115 };
116}
117
118#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, GenericOverIp)]
126#[generic_over_ip(I, Ip)]
127pub struct IpVersionMarker<I: Ip> {
128 _marker: core::marker::PhantomData<I>,
129}
130
131impl<I: Ip> IpVersionMarker<I> {
132 pub const fn new() -> Self {
136 Self { _marker: core::marker::PhantomData }
137 }
138}
139
140impl<I: Ip> Default for IpVersionMarker<I> {
141 fn default() -> Self {
142 Self { _marker: core::marker::PhantomData }
143 }
144}
145
146impl<I: Ip> Debug for IpVersionMarker<I> {
147 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
148 write!(f, "IpVersionMarker<{}>", I::NAME)
149 }
150}
151
152#[allow(missing_docs)]
161#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
162pub enum IpAddr<V4 = Ipv4Addr, V6 = Ipv6Addr> {
163 V4(V4),
164 V6(V6),
165}
166
167impl<V4: Display, V6: Display> Display for IpAddr<V4, V6> {
168 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
169 match self {
170 Self::V4(v4) => v4.fmt(f),
171 Self::V6(v6) => v6.fmt(f),
172 }
173 }
174}
175
176impl<V4, V6> IpAddr<V4, V6> {
177 pub fn transpose<W: IpAddrWitness<V4 = V4, V6 = V6>>(self) -> W {
184 match self {
185 IpAddr::V4(addr) => W::from_v4(addr),
186 IpAddr::V6(addr) => W::from_v6(addr),
187 }
188 }
189}
190
191impl<A: IpAddress> From<A> for IpAddr {
192 #[inline]
193 fn from(addr: A) -> IpAddr {
194 addr.to_ip_addr()
195 }
196}
197
198impl<A: IpAddress, const N: usize> From<[A; N]> for IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
199 #[inline]
200 fn from(addrs: [A; N]) -> Self {
201 A::array_into_ip_addr(addrs)
202 }
203}
204
205#[cfg(feature = "std")]
206impl From<net::IpAddr> for IpAddr {
207 #[inline]
208 fn from(addr: net::IpAddr) -> IpAddr {
209 match addr {
210 net::IpAddr::V4(addr) => IpAddr::V4(addr.into()),
211 net::IpAddr::V6(addr) => IpAddr::V6(addr.into()),
212 }
213 }
214}
215
216#[cfg(feature = "std")]
217impl From<IpAddr> for net::IpAddr {
218 fn from(addr: IpAddr) -> net::IpAddr {
219 match addr {
220 IpAddr::V4(addr) => net::IpAddr::V4(addr.into()),
221 IpAddr::V6(addr) => net::IpAddr::V6(addr.into()),
222 }
223 }
224}
225
226impl IpVersion {
227 #[inline]
231 pub fn version_number(self) -> u8 {
232 match self {
233 IpVersion::V4 => 4,
234 IpVersion::V6 => 6,
235 }
236 }
237
238 #[inline]
240 pub fn is_v4(self) -> bool {
241 self == IpVersion::V4
242 }
243
244 #[inline]
246 pub fn is_v6(self) -> bool {
247 self == IpVersion::V6
248 }
249}
250
251#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
254pub struct Mtu(u32);
255
256impl Mtu {
257 pub const fn new(mtu: u32) -> Self {
259 Self(mtu)
260 }
261
262 pub const fn get(&self) -> u32 {
264 let Self(mtu) = self;
265 *mtu
266 }
267
268 pub const fn max() -> Self {
270 Self(u32::MAX)
271 }
272
273 pub const fn no_limit() -> Self {
277 Self::max()
278 }
279}
280
281impl From<Mtu> for u32 {
282 fn from(Mtu(mtu): Mtu) -> Self {
283 mtu
284 }
285}
286
287impl From<Mtu> for usize {
288 fn from(Mtu(mtu): Mtu) -> Self {
289 mtu.try_into().expect("mtu must fit usize")
290 }
291}
292
293pub trait Ip:
308 Sized
309 + Clone
310 + Copy
311 + Debug
312 + Default
313 + Eq
314 + Hash
315 + Ord
316 + PartialEq
317 + PartialOrd
318 + Send
319 + Sync
320 + sealed::Sealed
321 + 'static
322{
323 const VERSION: IpVersion;
327
328 const VERSION_MARKER: IpVersionMarker<Self>;
330
331 const UNSPECIFIED_ADDRESS: Self::Addr;
335
336 const LOOPBACK_ADDRESS: SpecifiedAddr<Self::Addr>;
343
344 const LOOPBACK_SUBNET: Subnet<Self::Addr>;
349
350 const MULTICAST_SUBNET: Subnet<Self::Addr>;
352
353 const LINK_LOCAL_UNICAST_SUBNET: Subnet<Self::Addr>;
363
364 const NAME: &'static str;
366
367 const MINIMUM_LINK_MTU: Mtu;
374
375 type Addr: IpAddress<Version = Self>
379 + GenericOverIp<Self, Type = Self::Addr>
380 + GenericOverIp<Ipv4, Type = Ipv4Addr>
381 + GenericOverIp<Ipv6, Type = Ipv6Addr>;
382
383 fn map_ip<
414 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
415 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
416 >(
417 input: In,
418 v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
419 v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
420 ) -> Out;
421
422 fn map_ip_in<
429 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
430 Out,
431 >(
432 input: In,
433 v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> Out,
434 v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> Out,
435 ) -> Out {
436 Self::map_ip::<_, IpInvariant<_>>(
437 input,
438 |input| IpInvariant(v4(input)),
439 |input| IpInvariant(v6(input)),
440 )
441 .into_inner()
442 }
443
444 fn map_ip_out<
451 In,
452 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
453 >(
454 input: In,
455 v4: impl FnOnce(In) -> <Out as GenericOverIp<Ipv4>>::Type,
456 v6: impl FnOnce(In) -> <Out as GenericOverIp<Ipv6>>::Type,
457 ) -> Out {
458 Self::map_ip(
459 IpInvariant(input),
460 |IpInvariant(input)| v4(input),
461 |IpInvariant(input)| v6(input),
462 )
463 }
464}
465
466#[macro_export]
535macro_rules! map_ip_twice {
536 ($ip:ident, $input:expr, $fn:expr $(,)?) => {
540 $crate::map_ip_twice!($ip as $ip, $input, $fn)
541 };
542 ($ip:ty, $input:expr, $fn:expr $(,)?) => {
546 <$ip as $crate::ip::Ip>::map_ip($input, { $fn }, { $fn })
547 };
548 ($ip:ty as $iptypealias:ident, $input:expr, $fn:expr $(,)?) => {
549 <$ip as $crate::ip::Ip>::map_ip(
550 $input,
551 {
552 #[allow(dead_code)]
553 type $iptypealias = $crate::ip::Ipv4;
554 $fn
555 },
556 {
557 #[allow(dead_code)]
558 type $iptypealias = $crate::ip::Ipv6;
559 $fn
560 },
561 )
562 };
563}
564
565#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
572pub enum Ipv4 {}
573
574impl Default for Ipv4 {
575 fn default() -> Ipv4 {
576 panic!("Ipv4 default")
577 }
578}
579
580impl sealed::Sealed for Ipv4 {}
581
582impl Ip for Ipv4 {
583 const VERSION: IpVersion = IpVersion::V4;
584 const VERSION_MARKER: IpVersionMarker<Self> = IpVersionMarker::new();
585
586 const UNSPECIFIED_ADDRESS: Ipv4Addr = Ipv4Addr::new([0, 0, 0, 0]);
589 const LOOPBACK_ADDRESS: SpecifiedAddr<Ipv4Addr> =
598 unsafe { SpecifiedAddr::new_unchecked(Ipv4Addr::new([127, 0, 0, 1])) };
599 const LOOPBACK_SUBNET: Subnet<Ipv4Addr> =
603 Subnet { network: Ipv4Addr::new([127, 0, 0, 0]), prefix: 8 };
604 const MULTICAST_SUBNET: Subnet<Ipv4Addr> = Self::CLASS_D_SUBNET;
608 const LINK_LOCAL_UNICAST_SUBNET: Subnet<Ipv4Addr> =
613 Subnet { network: Ipv4Addr::new([169, 254, 0, 0]), prefix: 16 };
614 const NAME: &'static str = "IPv4";
615 const MINIMUM_LINK_MTU: Mtu = Mtu(68);
622 type Addr = Ipv4Addr;
623
624 fn map_ip<
625 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
626 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
627 >(
628 input: In,
629 v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
630 _v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
631 ) -> Out {
632 v4(input)
633 }
634}
635
636impl Ipv4 {
637 pub const LIMITED_BROADCAST_ADDRESS: SpecifiedAddr<Ipv4Addr> =
647 unsafe { SpecifiedAddr::new_unchecked(Ipv4Addr::new([255, 255, 255, 255])) };
648
649 pub const CLASS_A_SUBNET: Subnet<Ipv4Addr> =
655 Subnet { network: Ipv4Addr::new([0, 0, 0, 0]), prefix: 1 };
656
657 pub const CLASS_B_SUBNET: Subnet<Ipv4Addr> =
663 Subnet { network: Ipv4Addr::new([128, 0, 0, 0]), prefix: 2 };
664
665 pub const CLASS_C_SUBNET: Subnet<Ipv4Addr> =
671 Subnet { network: Ipv4Addr::new([192, 0, 0, 0]), prefix: 3 };
672
673 pub const CLASS_D_SUBNET: Subnet<Ipv4Addr> =
681 Subnet { network: Ipv4Addr::new([224, 0, 0, 0]), prefix: 4 };
682
683 pub const CLASS_E_SUBNET: Subnet<Ipv4Addr> =
693 Subnet { network: Ipv4Addr::new([240, 0, 0, 0]), prefix: 4 };
694
695 pub const LINK_LOCAL_MULTICAST_SUBNET: Subnet<Ipv4Addr> =
700 Subnet { network: Ipv4Addr::new([224, 0, 0, 0]), prefix: 24 };
701
702 pub const ALL_SYSTEMS_MULTICAST_ADDRESS: MulticastAddr<Ipv4Addr> =
707 unsafe { MulticastAddr::new_unchecked(Ipv4Addr::new([224, 0, 0, 1])) };
708
709 pub const ALL_ROUTERS_MULTICAST_ADDRESS: MulticastAddr<Ipv4Addr> =
714 unsafe { MulticastAddr::new_unchecked(Ipv4Addr::new([224, 0, 0, 2])) };
715}
716
717#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
724pub enum Ipv6 {}
725
726impl Default for Ipv6 {
727 fn default() -> Ipv6 {
728 panic!("Ipv6 default")
729 }
730}
731
732impl sealed::Sealed for Ipv6 {}
733
734impl Ip for Ipv6 {
735 const VERSION: IpVersion = IpVersion::V6;
736 const VERSION_MARKER: IpVersionMarker<Self> = IpVersionMarker::new();
737 const UNSPECIFIED_ADDRESS: Ipv6Addr = Ipv6Addr::new([0; 8]);
753 const LOOPBACK_ADDRESS: SpecifiedAddr<Ipv6Addr> =
773 unsafe { SpecifiedAddr::new_unchecked(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1])) };
774 const LOOPBACK_SUBNET: Subnet<Ipv6Addr> =
782 Subnet { network: Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1]), prefix: 128 };
783 const MULTICAST_SUBNET: Subnet<Ipv6Addr> =
788 Subnet { network: Ipv6Addr::new([0xff00, 0, 0, 0, 0, 0, 0, 0]), prefix: 8 };
789 const LINK_LOCAL_UNICAST_SUBNET: Subnet<Ipv6Addr> =
799 Subnet { network: Ipv6Addr::new([0xfe80, 0, 0, 0, 0, 0, 0, 0]), prefix: 10 };
800 const NAME: &'static str = "IPv6";
801 const MINIMUM_LINK_MTU: Mtu = Mtu(1280);
813 type Addr = Ipv6Addr;
814
815 fn map_ip<
816 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
817 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
818 >(
819 input: In,
820 _v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
821 v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
822 ) -> Out {
823 v6(input)
824 }
825}
826
827impl Ipv6 {
828 pub const LOOPBACK_IPV6_ADDRESS: UnicastAddr<Ipv6Addr> =
835 unsafe { UnicastAddr::new_unchecked(Ipv6::LOOPBACK_ADDRESS.0) };
836
837 pub const ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS: MulticastAddr<Ipv6Addr> =
842 unsafe { MulticastAddr::new_unchecked(Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0, 0, 1])) };
843
844 pub const ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS: MulticastAddr<Ipv6Addr> =
849 unsafe { MulticastAddr::new_unchecked(Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0, 0, 2])) };
850
851 pub const SITE_LOCAL_UNICAST_SUBNET: Subnet<Ipv6Addr> =
865 Subnet { network: Ipv6Addr::new([0xfec0, 0, 0, 0, 0, 0, 0, 0]), prefix: 10 };
866
867 pub const UNICAST_INTERFACE_IDENTIFIER_BITS: u8 = 64;
892
893 pub const FLOW_LABEL_BITS: u8 = 20;
897}
898
899pub trait IpAddress:
906 Sized
907 + Eq
908 + PartialEq
909 + PartialOrd
910 + Ord
911 + Hash
912 + Copy
913 + Display
914 + Debug
915 + Default
916 + Sync
917 + Send
918 + LinkLocalAddress
919 + ScopeableAddress
920 + GenericOverIp<Self::Version, Type = Self>
921 + GenericOverIp<Ipv4, Type = Ipv4Addr>
922 + GenericOverIp<Ipv6, Type = Ipv6Addr>
923 + sealed::Sealed
924 + 'static
925{
926 const BYTES: u8;
930
931 type Version: Ip<Addr = Self>;
935
936 fn bytes(&self) -> &[u8];
938
939 fn mask(&self, bits: u8) -> Self;
949
950 fn to_ip_addr(&self) -> IpAddr;
952
953 #[inline]
960 fn is_loopback(&self) -> bool {
961 Self::Version::LOOPBACK_SUBNET.contains(self)
962 }
963
964 fn common_prefix_len(&self, other: &Self) -> u8;
966
967 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool;
1027
1028 #[doc(hidden)]
1034 fn subnet_into_either(subnet: Subnet<Self>) -> SubnetEither;
1035
1036 #[doc(hidden)]
1037 fn array_into_ip_addr<const N: usize>(addrs: [Self; N])
1038 -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]>;
1039}
1040
1041impl<A: IpAddress> SpecifiedAddress for A {
1042 #[inline]
1049 fn is_specified(&self) -> bool {
1050 self != &A::Version::UNSPECIFIED_ADDRESS
1051 }
1052}
1053
1054macro_rules! map_ip_addr {
1057 ($val:expr, $method:ident) => {
1058 match $val {
1059 IpAddr::V4(a) => a.$method(),
1060 IpAddr::V6(a) => a.$method(),
1061 }
1062 };
1063}
1064
1065impl SpecifiedAddress for IpAddr {
1066 #[inline]
1071 fn is_specified(&self) -> bool {
1072 map_ip_addr!(self, is_specified)
1073 }
1074}
1075
1076impl<A: IpAddress> MulticastAddress for A {
1077 #[inline]
1084 fn is_multicast(&self) -> bool {
1085 <A as IpAddress>::Version::MULTICAST_SUBNET.contains(self)
1086 }
1087}
1088
1089impl MulticastAddress for IpAddr {
1090 #[inline]
1095 fn is_multicast(&self) -> bool {
1096 map_ip_addr!(self, is_multicast)
1097 }
1098}
1099
1100impl LinkLocalAddress for Ipv4Addr {
1101 #[inline]
1107 fn is_link_local(&self) -> bool {
1108 Ipv4::LINK_LOCAL_UNICAST_SUBNET.contains(self)
1109 || Ipv4::LINK_LOCAL_MULTICAST_SUBNET.contains(self)
1110 }
1111}
1112
1113impl LinkLocalAddress for Ipv6Addr {
1114 #[inline]
1124 fn is_link_local(&self) -> bool {
1125 Ipv6::LINK_LOCAL_UNICAST_SUBNET.contains(self)
1126 || (self.is_multicast() && self.scope() == Ipv6Scope::LinkLocal)
1127 || self == Ipv6::LOOPBACK_ADDRESS.deref()
1128 }
1129}
1130
1131impl LinkLocalAddress for IpAddr {
1132 #[inline]
1134 fn is_link_local(&self) -> bool {
1135 map_ip_addr!(self, is_link_local)
1136 }
1137}
1138
1139impl<A: IpAddress> MappedAddress for A {
1140 #[inline]
1151 fn is_non_mapped(&self) -> bool {
1152 A::Version::map_ip(self, |_addr_v4| true, |addr_v6| addr_v6.to_ipv4_mapped().is_none())
1153 }
1154}
1155
1156impl MappedAddress for IpAddr {
1157 #[inline]
1159 fn is_non_mapped(&self) -> bool {
1160 map_ip_addr!(self, is_non_mapped)
1161 }
1162}
1163
1164impl<I: Ip> GenericOverIp<I> for Ipv4Addr {
1165 type Type = I::Addr;
1166}
1167
1168impl<I: Ip> GenericOverIp<I> for Ipv6Addr {
1169 type Type = I::Addr;
1170}
1171
1172impl ScopeableAddress for Ipv4Addr {
1173 type Scope = ();
1174
1175 fn scope(&self) {}
1180}
1181
1182#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1188pub enum Ipv6Scope {
1189 InterfaceLocal,
1191 LinkLocal,
1193 AdminLocal,
1195 SiteLocal,
1211 OrganizationLocal,
1213 Global,
1215 Reserved(Ipv6ReservedScope),
1219 Unassigned(Ipv6UnassignedScope),
1221}
1222
1223#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1228pub enum Ipv6ReservedScope {
1229 Scope0 = 0,
1231 Scope3 = 3,
1233 ScopeF = 0xF,
1235}
1236
1237#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1240pub enum Ipv6UnassignedScope {
1241 Scope6 = 6,
1243 Scope7 = 7,
1245 Scope9 = 9,
1247 ScopeA = 0xA,
1249 ScopeB = 0xB,
1251 ScopeC = 0xC,
1253 ScopeD = 0xD,
1255}
1256
1257impl Scope for Ipv6Scope {
1258 #[inline]
1259 fn can_have_zone(&self) -> bool {
1260 matches!(self, Ipv6Scope::LinkLocal)
1280 }
1281}
1282
1283impl Ipv6Scope {
1284 pub const MULTICAST_SCOPE_ID_INTERFACE_LOCAL: u8 = 1;
1289
1290 pub const MULTICAST_SCOPE_ID_LINK_LOCAL: u8 = 2;
1295
1296 pub const MULTICAST_SCOPE_ID_ADMIN_LOCAL: u8 = 4;
1301
1302 pub const MULTICAST_SCOPE_ID_SITE_LOCAL: u8 = 5;
1309
1310 pub const MULTICAST_SCOPE_ID_ORG_LOCAL: u8 = 8;
1315
1316 pub const MULTICAST_SCOPE_ID_GLOBAL: u8 = 0xE;
1321
1322 pub fn multicast_scope_id(&self) -> u8 {
1340 match self {
1341 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope0) => 0,
1342 Ipv6Scope::InterfaceLocal => Self::MULTICAST_SCOPE_ID_INTERFACE_LOCAL,
1343 Ipv6Scope::LinkLocal => Self::MULTICAST_SCOPE_ID_LINK_LOCAL,
1344 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope3) => 3,
1345 Ipv6Scope::AdminLocal => Self::MULTICAST_SCOPE_ID_ADMIN_LOCAL,
1346 Ipv6Scope::SiteLocal => Self::MULTICAST_SCOPE_ID_SITE_LOCAL,
1347 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope6) => 6,
1348 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope7) => 7,
1349 Ipv6Scope::OrganizationLocal => Self::MULTICAST_SCOPE_ID_ORG_LOCAL,
1350 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope9) => 9,
1351 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeA) => 0xA,
1352 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeB) => 0xB,
1353 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeC) => 0xC,
1354 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeD) => 0xD,
1355 Ipv6Scope::Global => Self::MULTICAST_SCOPE_ID_GLOBAL,
1356 Ipv6Scope::Reserved(Ipv6ReservedScope::ScopeF) => 0xF,
1357 }
1358 }
1359}
1360
1361impl ScopeableAddress for Ipv6Addr {
1362 type Scope = Ipv6Scope;
1363
1364 #[inline]
1366 fn scope(&self) -> Ipv6Scope {
1367 if self.is_multicast() {
1368 use Ipv6ReservedScope::*;
1369 use Ipv6Scope::*;
1370 use Ipv6UnassignedScope::*;
1371
1372 match self.0[1] & 0xF {
1376 0 => Reserved(Scope0),
1377 Ipv6Scope::MULTICAST_SCOPE_ID_INTERFACE_LOCAL => InterfaceLocal,
1378 Ipv6Scope::MULTICAST_SCOPE_ID_LINK_LOCAL => LinkLocal,
1379 3 => Reserved(Scope3),
1380 Ipv6Scope::MULTICAST_SCOPE_ID_ADMIN_LOCAL => AdminLocal,
1381 Ipv6Scope::MULTICAST_SCOPE_ID_SITE_LOCAL => SiteLocal,
1382 6 => Unassigned(Scope6),
1383 7 => Unassigned(Scope7),
1384 Ipv6Scope::MULTICAST_SCOPE_ID_ORG_LOCAL => OrganizationLocal,
1385 9 => Unassigned(Scope9),
1386 0xA => Unassigned(ScopeA),
1387 0xB => Unassigned(ScopeB),
1388 0xC => Unassigned(ScopeC),
1389 0xD => Unassigned(ScopeD),
1390 Ipv6Scope::MULTICAST_SCOPE_ID_GLOBAL => Global,
1391 0xF => Reserved(ScopeF),
1392 _ => unreachable!(),
1393 }
1394 } else if self.is_link_local() {
1395 Ipv6Scope::LinkLocal
1396 } else if self.is_site_local() {
1397 Ipv6Scope::SiteLocal
1398 } else {
1399 Ipv6Scope::Global
1400 }
1401 }
1402}
1403
1404impl Scope for IpAddr<(), Ipv6Scope> {
1405 #[inline]
1406 fn can_have_zone(&self) -> bool {
1407 match self {
1408 IpAddr::V4(scope) => scope.can_have_zone(),
1409 IpAddr::V6(scope) => scope.can_have_zone(),
1410 }
1411 }
1412}
1413
1414impl ScopeableAddress for IpAddr {
1415 type Scope = IpAddr<(), Ipv6Scope>;
1416
1417 #[inline]
1418 fn scope(&self) -> IpAddr<(), Ipv6Scope> {
1419 match self {
1420 IpAddr::V4(_) => IpAddr::V4(()),
1421 IpAddr::V6(addr) => IpAddr::V6(addr.scope()),
1422 }
1423 }
1424}
1425
1426macro_rules! impl_from_witness {
1449 ($witness:ident, $witness_trait:ident) => {
1450 impl From<IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>> for $witness<IpAddr> {
1451 fn from(addr: IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>) -> $witness<IpAddr> {
1452 unsafe {
1453 Witness::new_unchecked(match addr {
1454 IpAddr::V4(addr) => IpAddr::V4(addr.get()),
1455 IpAddr::V6(addr) => IpAddr::V6(addr.get()),
1456 })
1457 }
1458 }
1459 }
1460 impl From<$witness<IpAddr>> for IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1461 fn from(addr: $witness<IpAddr>) -> IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1462 unsafe {
1463 match addr.get() {
1464 IpAddr::V4(addr) => IpAddr::V4(Witness::new_unchecked(addr)),
1465 IpAddr::V6(addr) => IpAddr::V6(Witness::new_unchecked(addr)),
1466 }
1467 }
1468 }
1469 }
1470 impl<A: IpAddress> From<$witness<A>> for $witness<IpAddr> {
1471 fn from(addr: $witness<A>) -> $witness<IpAddr> {
1472 unsafe { Witness::new_unchecked(addr.to_ip_addr()) }
1473 }
1474 }
1475 impl<A: IpAddress> From<$witness<A>> for IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1476 fn from(addr: $witness<A>) -> IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1477 let addr: $witness<IpAddr> = addr.into();
1478 addr.into()
1479 }
1480 }
1481 impl<A: Into<Ipv4Addr> + $witness_trait + Copy> From<$witness<A>> for Ipv4Addr {
1483 fn from(addr: $witness<A>) -> Ipv4Addr {
1484 let addr: A = addr.get();
1485 addr.into()
1486 }
1487 }
1488 impl<A: Into<Ipv6Addr> + $witness_trait + Copy> From<$witness<A>> for Ipv6Addr {
1489 fn from(addr: $witness<A>) -> Ipv6Addr {
1490 let addr: A = addr.get();
1491 addr.into()
1492 }
1493 }
1494 impl TryFrom<Ipv4Addr> for $witness<Ipv4Addr> {
1496 type Error = ();
1497 fn try_from(addr: Ipv4Addr) -> Result<$witness<Ipv4Addr>, ()> {
1498 Witness::new(addr).ok_or(())
1499 }
1500 }
1501 impl TryFrom<Ipv6Addr> for $witness<Ipv6Addr> {
1502 type Error = ();
1503 fn try_from(addr: Ipv6Addr) -> Result<$witness<Ipv6Addr>, ()> {
1504 Witness::new(addr).ok_or(())
1505 }
1506 }
1507 };
1508 ($witness:ident, $witness_trait:ident, $ipaddr:ident, $new_unchecked:expr) => {
1509 impl From<$witness<$ipaddr>> for $witness<IpAddr> {
1510 fn from(addr: $witness<$ipaddr>) -> $witness<IpAddr> {
1511 let addr: $ipaddr = addr.get();
1512 let addr: IpAddr = addr.into();
1513 #[allow(unused_unsafe)] unsafe {
1515 $new_unchecked(addr)
1516 }
1517 }
1518 }
1519 impl<A: Into<$ipaddr> + $witness_trait + Copy> From<$witness<A>> for $ipaddr {
1520 fn from(addr: $witness<A>) -> $ipaddr {
1521 let addr: A = addr.get();
1522 addr.into()
1523 }
1524 }
1525 impl TryFrom<$ipaddr> for $witness<$ipaddr> {
1526 type Error = ();
1527 fn try_from(addr: $ipaddr) -> Result<$witness<$ipaddr>, ()> {
1528 Witness::new(addr).ok_or(())
1529 }
1530 }
1531 };
1532}
1533
1534impl_from_witness!(SpecifiedAddr, SpecifiedAddress);
1535impl_from_witness!(MulticastAddr, MulticastAddress);
1536impl_from_witness!(LinkLocalAddr, LinkLocalAddress);
1537impl_from_witness!(NonMappedAddr, MappedAddress);
1538impl_from_witness!(UnicastAddr, UnicastAddress, Ipv6Addr, UnicastAddr::new_unchecked);
1541
1542#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1552pub enum Ipv4AddressClass {
1553 A,
1555 B,
1557 C,
1559 D,
1563 E,
1567}
1568
1569impl Ipv4AddressClass {
1570 pub const fn default_prefix_len(self) -> Option<u8> {
1573 match self {
1611 Ipv4AddressClass::A => Some(8),
1612 Ipv4AddressClass::B => Some(16),
1613 Ipv4AddressClass::C => Some(24),
1614 Ipv4AddressClass::D => None,
1615 Ipv4AddressClass::E => None,
1616 }
1617 }
1618}
1619
1620#[derive(
1643 Copy,
1644 Clone,
1645 Default,
1646 PartialEq,
1647 Eq,
1648 PartialOrd,
1649 Ord,
1650 Hash,
1651 KnownLayout,
1652 FromBytes,
1653 IntoBytes,
1654 Immutable,
1655 Unaligned,
1656)]
1657#[repr(transparent)]
1658pub struct Ipv4Addr([u8; 4]);
1659
1660impl Ipv4Addr {
1661 #[inline]
1663 pub const fn new(bytes: [u8; 4]) -> Self {
1664 Ipv4Addr(bytes)
1665 }
1666
1667 #[inline]
1669 pub const fn ipv4_bytes(self) -> [u8; 4] {
1670 self.0
1671 }
1672
1673 #[inline]
1678 pub fn is_limited_broadcast(self) -> bool {
1679 self == Ipv4::LIMITED_BROADCAST_ADDRESS.get()
1680 }
1681
1682 #[inline]
1687 pub fn is_class_e(self) -> bool {
1688 Ipv4::CLASS_E_SUBNET.contains(&self)
1689 }
1690
1691 #[inline]
1719 pub fn to_ipv6_compatible(self) -> Ipv6Addr {
1720 let Self([a, b, c, d]) = self;
1721 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
1722 }
1723
1724 #[inline]
1742 pub fn to_ipv6_mapped(self) -> SpecifiedAddr<Ipv6Addr> {
1743 let Self([a, b, c, d]) = self;
1744 SpecifiedAddr::new(Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d]))
1745 .unwrap()
1746 }
1747
1748 pub fn class(&self) -> Ipv4AddressClass {
1751 for (subnet, class) in [
1752 (Ipv4::CLASS_A_SUBNET, Ipv4AddressClass::A),
1753 (Ipv4::CLASS_B_SUBNET, Ipv4AddressClass::B),
1754 (Ipv4::CLASS_C_SUBNET, Ipv4AddressClass::C),
1755 (Ipv4::CLASS_D_SUBNET, Ipv4AddressClass::D),
1756 (Ipv4::CLASS_E_SUBNET, Ipv4AddressClass::E),
1757 ] {
1758 if subnet.contains(self) {
1759 return class;
1760 }
1761 }
1762
1763 unreachable!("{} should fit into a class", self)
1764 }
1765}
1766
1767impl sealed::Sealed for Ipv4Addr {}
1768
1769impl IpAddress for Ipv4Addr {
1770 const BYTES: u8 = 4;
1771
1772 type Version = Ipv4;
1773
1774 #[inline]
1775 fn mask(&self, bits: u8) -> Self {
1776 assert!(bits <= 32);
1777 let mask = u32::MAX.checked_shl((32 - bits).into()).unwrap_or(0);
1781 Ipv4Addr((u32::from_be_bytes(self.0) & mask).to_be_bytes())
1782 }
1783
1784 #[inline]
1785 fn bytes(&self) -> &[u8] {
1786 &self.0
1787 }
1788
1789 #[inline]
1790 fn to_ip_addr(&self) -> IpAddr {
1791 IpAddr::V4(*self)
1792 }
1793
1794 #[inline]
1795 fn common_prefix_len(&self, other: &Ipv4Addr) -> u8 {
1796 let me = u32::from_be_bytes(self.0);
1797 let other = u32::from_be_bytes(other.0);
1798 let same_bits = me ^ other;
1801 same_bits.leading_zeros() as u8
1802 }
1803
1804 #[inline]
1805 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool {
1806 !self.is_multicast()
1807 && !self.is_limited_broadcast()
1808 && (subnet.prefix() == 32
1812 || subnet.prefix() == 31
1813 || (*self != subnet.broadcast() && *self != subnet.network()))
1814 && self.is_specified()
1815 && !self.is_class_e()
1816 && subnet.contains(self)
1817 }
1818
1819 fn subnet_into_either(subnet: Subnet<Ipv4Addr>) -> SubnetEither {
1820 SubnetEither::V4(subnet)
1821 }
1822
1823 #[inline]
1824 fn array_into_ip_addr<const N: usize>(
1825 addrs: [Self; N],
1826 ) -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
1827 IpAddr::V4(addrs)
1828 }
1829}
1830
1831impl From<[u8; 4]> for Ipv4Addr {
1832 #[inline]
1833 fn from(bytes: [u8; 4]) -> Ipv4Addr {
1834 Ipv4Addr(bytes)
1835 }
1836}
1837
1838#[cfg(feature = "std")]
1839impl From<net::Ipv4Addr> for Ipv4Addr {
1840 #[inline]
1841 fn from(ip: net::Ipv4Addr) -> Ipv4Addr {
1842 Ipv4Addr::new(ip.octets())
1843 }
1844}
1845
1846#[cfg(feature = "std")]
1847impl From<Ipv4Addr> for net::Ipv4Addr {
1848 #[inline]
1849 fn from(ip: Ipv4Addr) -> net::Ipv4Addr {
1850 net::Ipv4Addr::from(ip.0)
1851 }
1852}
1853
1854impl Display for Ipv4Addr {
1855 #[inline]
1856 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1857 write!(f, "{}.{}.{}.{}", self.0[0], self.0[1], self.0[2], self.0[3])
1858 }
1859}
1860
1861impl Debug for Ipv4Addr {
1862 #[inline]
1863 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1864 Display::fmt(self, f)
1865 }
1866}
1867
1868#[allow(missing_docs)]
1875#[derive(Copy, Clone, Eq, PartialEq)]
1876pub enum Ipv4SourceAddr {
1877 Specified(NonMulticastAddr<SpecifiedAddr<Ipv4Addr>>),
1878 Unspecified,
1879}
1880
1881impl crate::sealed::Sealed for Ipv4SourceAddr {}
1882
1883impl Ipv4SourceAddr {
1884 #[inline]
1889 pub fn new(addr: Ipv4Addr) -> Option<Ipv4SourceAddr> {
1890 match SpecifiedAddr::new(addr) {
1891 Some(addr) => NonMulticastAddr::new(addr).map(Ipv4SourceAddr::Specified),
1892 None => Some(Ipv4SourceAddr::Unspecified),
1893 }
1894 }
1895}
1896
1897impl Witness<Ipv4Addr> for Ipv4SourceAddr {
1898 #[inline]
1899 fn new(addr: Ipv4Addr) -> Option<Ipv4SourceAddr> {
1900 Ipv4SourceAddr::new(addr)
1901 }
1902
1903 #[inline]
1904 unsafe fn new_unchecked(addr: Ipv4Addr) -> Ipv4SourceAddr {
1905 Ipv4SourceAddr::new(addr).unwrap()
1906 }
1907
1908 #[inline]
1909 fn into_addr(self) -> Ipv4Addr {
1910 match self {
1911 Ipv4SourceAddr::Specified(addr) => **addr,
1912 Ipv4SourceAddr::Unspecified => Ipv4::UNSPECIFIED_ADDRESS,
1913 }
1914 }
1915}
1916
1917impl From<Ipv4SourceAddr> for Ipv4Addr {
1918 fn from(addr: Ipv4SourceAddr) -> Ipv4Addr {
1919 addr.get()
1920 }
1921}
1922
1923impl AsRef<Ipv4Addr> for Ipv4SourceAddr {
1924 fn as_ref(&self) -> &Ipv4Addr {
1925 match self {
1926 Ipv4SourceAddr::Specified(addr) => addr,
1927 Ipv4SourceAddr::Unspecified => &Ipv4::UNSPECIFIED_ADDRESS,
1928 }
1929 }
1930}
1931
1932impl Deref for Ipv4SourceAddr {
1933 type Target = Ipv4Addr;
1934
1935 fn deref(&self) -> &Ipv4Addr {
1936 self.as_ref()
1937 }
1938}
1939
1940impl Display for Ipv4SourceAddr {
1941 #[inline]
1942 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1943 write!(f, "{}", self.get())
1944 }
1945}
1946
1947impl Debug for Ipv4SourceAddr {
1948 #[inline]
1949 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1950 Display::fmt(self, f)
1951 }
1952}
1953
1954#[derive(
1989 Copy,
1990 Clone,
1991 Default,
1992 PartialEq,
1993 Eq,
1994 PartialOrd,
1995 Ord,
1996 Hash,
1997 KnownLayout,
1998 FromBytes,
1999 IntoBytes,
2000 Immutable,
2001 Unaligned,
2002)]
2003#[repr(transparent)]
2004pub struct Ipv6Addr([u8; 16]);
2005
2006impl Ipv6Addr {
2007 #[inline]
2009 pub const fn new(segments: [u16; 8]) -> Ipv6Addr {
2010 #![allow(clippy::many_single_char_names)]
2011 let [a, b, c, d, e, f, g, h] = segments;
2012 let [aa, ab] = a.to_be_bytes();
2013 let [ba, bb] = b.to_be_bytes();
2014 let [ca, cb] = c.to_be_bytes();
2015 let [da, db] = d.to_be_bytes();
2016 let [ea, eb] = e.to_be_bytes();
2017 let [fa, fb] = f.to_be_bytes();
2018 let [ga, gb] = g.to_be_bytes();
2019 let [ha, hb] = h.to_be_bytes();
2020 Ipv6Addr([aa, ab, ba, bb, ca, cb, da, db, ea, eb, fa, fb, ga, gb, ha, hb])
2021 }
2022
2023 #[inline]
2025 pub const fn from_bytes(bytes: [u8; 16]) -> Ipv6Addr {
2026 Ipv6Addr(bytes)
2027 }
2028
2029 #[inline]
2031 pub const fn ipv6_bytes(&self) -> [u8; 16] {
2032 self.0
2033 }
2034
2035 #[inline]
2037 pub fn segments(&self) -> [u16; 8] {
2038 #![allow(clippy::many_single_char_names)]
2039 let [a, b, c, d, e, f, g, h]: [zerocopy::network_endian::U16; 8] =
2040 zerocopy::transmute!(self.ipv6_bytes());
2041 [a.into(), b.into(), c.into(), d.into(), e.into(), f.into(), g.into(), h.into()]
2042 }
2043
2044 #[inline]
2049 pub const fn to_solicited_node_address(&self) -> MulticastAddr<Ipv6Addr> {
2050 unsafe {
2058 MulticastAddr::new_unchecked(Ipv6Addr::from_bytes([
2059 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xff, self.0[13], self.0[14],
2060 self.0[15],
2061 ]))
2062 }
2063 }
2064
2065 #[inline]
2072 pub fn is_valid_unicast(&self) -> bool {
2073 !(self.is_loopback() || !self.is_specified() || self.is_multicast())
2074 }
2075
2076 #[inline]
2083 pub fn is_site_local(&self) -> bool {
2084 Ipv6::SITE_LOCAL_UNICAST_SUBNET.contains(self)
2085 }
2086
2087 #[inline]
2092 pub fn is_unicast_link_local(&self) -> bool {
2093 self.is_unicast_in_subnet(&Ipv6::LINK_LOCAL_UNICAST_SUBNET)
2094 }
2095
2096 pub fn to_ipv4_compatible(&self) -> Option<Ipv4Addr> {
2126 if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] = self.0 {
2127 Some(Ipv4Addr::new([a, b, c, d]))
2128 } else {
2129 None
2130 }
2131 }
2132
2133 pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
2153 if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] = self.0 {
2154 Some(Ipv4Addr::new([a, b, c, d]))
2155 } else {
2156 None
2157 }
2158 }
2159}
2160
2161impl sealed::Sealed for Ipv6Addr {}
2162
2163impl From<Ipv4Addr> for Ipv6Addr {
2166 fn from(addr: Ipv4Addr) -> Ipv6Addr {
2167 *addr.to_ipv6_mapped()
2168 }
2169}
2170
2171impl IpAddress for Ipv6Addr {
2172 const BYTES: u8 = 16;
2173
2174 type Version = Ipv6;
2175
2176 #[inline]
2177 fn mask(&self, bits: u8) -> Ipv6Addr {
2178 assert!(bits <= 128);
2179 let mask = u128::MAX.checked_shl((128 - bits).into()).unwrap_or(0);
2183 Ipv6Addr((u128::from_be_bytes(self.0) & mask).to_be_bytes())
2184 }
2185
2186 #[inline]
2187 fn bytes(&self) -> &[u8] {
2188 &self.0
2189 }
2190
2191 #[inline]
2192 fn to_ip_addr(&self) -> IpAddr {
2193 IpAddr::V6(*self)
2194 }
2195
2196 #[inline]
2197 fn common_prefix_len(&self, other: &Ipv6Addr) -> u8 {
2198 let me = u128::from_be_bytes(self.0);
2199 let other = u128::from_be_bytes(other.0);
2200 let same_bits = me ^ other;
2203 same_bits.leading_zeros() as u8
2204 }
2205
2206 #[inline]
2207 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool {
2208 !self.is_multicast() && self.is_specified() && subnet.contains(self)
2209 }
2210
2211 fn subnet_into_either(subnet: Subnet<Ipv6Addr>) -> SubnetEither {
2212 SubnetEither::V6(subnet)
2213 }
2214
2215 #[inline]
2216 fn array_into_ip_addr<const N: usize>(
2217 addrs: [Self; N],
2218 ) -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
2219 IpAddr::V6(addrs)
2220 }
2221}
2222
2223impl UnicastAddress for Ipv6Addr {
2224 #[inline]
2229 fn is_unicast(&self) -> bool {
2230 !self.is_multicast() && self.is_specified()
2231 }
2232}
2233
2234impl From<[u8; 16]> for Ipv6Addr {
2235 #[inline]
2236 fn from(bytes: [u8; 16]) -> Ipv6Addr {
2237 Ipv6Addr::from_bytes(bytes)
2238 }
2239}
2240
2241#[cfg(feature = "std")]
2242impl From<net::Ipv6Addr> for Ipv6Addr {
2243 #[inline]
2244 fn from(addr: net::Ipv6Addr) -> Ipv6Addr {
2245 Ipv6Addr::from_bytes(addr.octets())
2246 }
2247}
2248
2249#[cfg(feature = "std")]
2250impl From<Ipv6Addr> for net::Ipv6Addr {
2251 #[inline]
2252 fn from(addr: Ipv6Addr) -> net::Ipv6Addr {
2253 net::Ipv6Addr::from(addr.ipv6_bytes())
2254 }
2255}
2256
2257impl Display for Ipv6Addr {
2258 #[inline]
2267 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2268 fn fmt_inner<W: fmt::Write>(addr: &Ipv6Addr, w: &mut W) -> Result<(), fmt::Error> {
2273 if !addr.is_specified() {
2277 write!(w, "::")
2278 } else if addr.is_loopback() {
2279 write!(w, "::1")
2280 } else if let Some(v4) = addr.to_ipv4_mapped() {
2281 write!(w, "::ffff:{}", v4)
2282 } else {
2283 let segments = addr.segments();
2284
2285 let longest_zero_span = {
2286 let mut longest_zero_span = 0..0;
2287 let mut current_zero_span = 0..0;
2288 for (i, seg) in segments.iter().enumerate() {
2289 if *seg == 0 {
2290 current_zero_span.end = i + 1;
2291 if current_zero_span.len() > longest_zero_span.len() {
2292 longest_zero_span = current_zero_span.clone();
2293 }
2294 } else {
2295 let next_idx = i + 1;
2296 current_zero_span = next_idx..next_idx;
2297 }
2298 }
2299 longest_zero_span
2300 };
2301
2302 let write_slice = |w: &mut W, slice: &[u16]| {
2303 if let [head, tail @ ..] = slice {
2304 write!(w, "{:x}", head)?;
2305 for seg in tail {
2306 write!(w, ":{:x}", seg)?;
2307 }
2308 }
2309 Ok(())
2310 };
2311
2312 if longest_zero_span.len() > 1 {
2329 write_slice(w, &segments[..longest_zero_span.start])?;
2330 w.write_str("::")?;
2331 write_slice(w, &segments[longest_zero_span.end..])
2332 } else {
2333 write_slice(w, &segments)
2334 }
2335 }
2336 }
2337
2338 if f.precision().is_none() && f.width().is_none() {
2339 fmt_inner(self, f)
2342 } else {
2343 struct ByteSlice<'a>(&'a mut [u8]);
2350
2351 impl<'a> fmt::Write for ByteSlice<'a> {
2352 fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
2353 let from = s.as_bytes();
2354
2355 if from.len() > self.0.len() {
2356 return Err(fmt::Error);
2357 }
2358
2359 let to = mem::replace(&mut self.0, &mut [][..]);
2365 let (to, remaining) = to.split_at_mut(from.len());
2366 to.copy_from_slice(from);
2367
2368 self.0 = remaining;
2369 Ok(())
2370 }
2371 }
2372
2373 const MAX_DISPLAY_LEN: usize = (4 * 8) + 7;
2377 let mut scratch = [0u8; MAX_DISPLAY_LEN];
2378 let mut scratch_slice = ByteSlice(&mut scratch[..]);
2379 fmt_inner(self, &mut scratch_slice)
2386 .expect("<Ipv6Addr as Display>::fmt: fmt_inner should have succeeded because the scratch buffer was long enough");
2387 let unwritten = scratch_slice.0.len();
2388 let len = MAX_DISPLAY_LEN - unwritten;
2389 let str = core::str::from_utf8(&scratch[..len])
2391 .expect("<Ipv6Addr as Display>::fmt: scratch buffer should contain valid UTF-8");
2392 f.pad(str)
2393 }
2394 }
2395}
2396
2397impl Debug for Ipv6Addr {
2398 #[inline]
2399 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2400 Display::fmt(self, f)
2401 }
2402}
2403
2404#[allow(missing_docs)]
2411#[derive(Copy, Clone, Eq, PartialEq)]
2412pub enum Ipv6SourceAddr {
2413 Unicast(NonMappedAddr<UnicastAddr<Ipv6Addr>>),
2414 Unspecified,
2415}
2416
2417impl crate::sealed::Sealed for Ipv6SourceAddr {}
2418
2419impl Ipv6SourceAddr {
2420 #[inline]
2425 pub fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2426 if let Some(addr) = UnicastAddr::new(addr) {
2427 NonMappedAddr::new(addr).map(Ipv6SourceAddr::Unicast)
2428 } else if !addr.is_specified() {
2429 Some(Ipv6SourceAddr::Unspecified)
2430 } else {
2431 None
2432 }
2433 }
2434}
2435
2436impl Witness<Ipv6Addr> for Ipv6SourceAddr {
2437 #[inline]
2438 fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2439 Ipv6SourceAddr::new(addr)
2440 }
2441
2442 #[inline]
2443 unsafe fn new_unchecked(addr: Ipv6Addr) -> Ipv6SourceAddr {
2444 Ipv6SourceAddr::new(addr).unwrap()
2445 }
2446
2447 #[inline]
2448 fn into_addr(self) -> Ipv6Addr {
2449 match self {
2450 Ipv6SourceAddr::Unicast(addr) => **addr,
2451 Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2452 }
2453 }
2454}
2455
2456impl SpecifiedAddress for Ipv6SourceAddr {
2457 fn is_specified(&self) -> bool {
2458 self != &Ipv6SourceAddr::Unspecified
2459 }
2460}
2461
2462impl UnicastAddress for Ipv6SourceAddr {
2463 fn is_unicast(&self) -> bool {
2464 matches!(self, Ipv6SourceAddr::Unicast(_))
2465 }
2466}
2467
2468impl LinkLocalAddress for Ipv6SourceAddr {
2469 fn is_link_local(&self) -> bool {
2470 let addr: Ipv6Addr = self.into();
2471 addr.is_link_local()
2472 }
2473}
2474
2475impl MappedAddress for Ipv6SourceAddr {
2476 fn is_non_mapped(&self) -> bool {
2477 let addr: Ipv6Addr = self.into();
2478 addr.is_non_mapped()
2479 }
2480}
2481
2482impl From<Ipv6SourceAddr> for Ipv6Addr {
2483 fn from(addr: Ipv6SourceAddr) -> Ipv6Addr {
2484 addr.get()
2485 }
2486}
2487
2488impl From<&'_ Ipv6SourceAddr> for Ipv6Addr {
2489 fn from(addr: &Ipv6SourceAddr) -> Ipv6Addr {
2490 match addr {
2491 Ipv6SourceAddr::Unicast(addr) => addr.get(),
2492 Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2493 }
2494 }
2495}
2496
2497impl TryFrom<Ipv6Addr> for Ipv6SourceAddr {
2498 type Error = ();
2499 fn try_from(addr: Ipv6Addr) -> Result<Ipv6SourceAddr, ()> {
2500 Ipv6SourceAddr::new(addr).ok_or(())
2501 }
2502}
2503
2504impl AsRef<Ipv6Addr> for Ipv6SourceAddr {
2505 fn as_ref(&self) -> &Ipv6Addr {
2506 match self {
2507 Ipv6SourceAddr::Unicast(addr) => addr,
2508 Ipv6SourceAddr::Unspecified => &Ipv6::UNSPECIFIED_ADDRESS,
2509 }
2510 }
2511}
2512
2513impl Deref for Ipv6SourceAddr {
2514 type Target = Ipv6Addr;
2515
2516 fn deref(&self) -> &Ipv6Addr {
2517 self.as_ref()
2518 }
2519}
2520
2521impl Display for Ipv6SourceAddr {
2522 #[inline]
2523 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2524 match self {
2525 Ipv6SourceAddr::Unicast(addr) => write!(f, "{}", addr),
2526 Ipv6SourceAddr::Unspecified => write!(f, "::"),
2527 }
2528 }
2529}
2530
2531impl Debug for Ipv6SourceAddr {
2532 #[inline]
2533 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2534 Display::fmt(self, f)
2535 }
2536}
2537
2538#[allow(missing_docs)]
2546#[derive(Copy, Clone, Eq, PartialEq)]
2547pub enum UnicastOrMulticastIpv6Addr {
2548 Unicast(UnicastAddr<Ipv6Addr>),
2549 Multicast(MulticastAddr<Ipv6Addr>),
2550}
2551
2552impl UnicastOrMulticastIpv6Addr {
2553 pub fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2557 SpecifiedAddr::new(addr).map(UnicastOrMulticastIpv6Addr::from_specified)
2558 }
2559
2560 pub fn from_specified(addr: SpecifiedAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2562 if addr.is_unicast() {
2563 UnicastOrMulticastIpv6Addr::Unicast(UnicastAddr(addr.get()))
2564 } else {
2565 UnicastOrMulticastIpv6Addr::Multicast(MulticastAddr(addr.get()))
2566 }
2567 }
2568}
2569
2570impl crate::sealed::Sealed for UnicastOrMulticastIpv6Addr {}
2571
2572impl Witness<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2573 #[inline]
2574 fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2575 UnicastOrMulticastIpv6Addr::new(addr)
2576 }
2577
2578 #[inline]
2579 unsafe fn new_unchecked(addr: Ipv6Addr) -> UnicastOrMulticastIpv6Addr {
2580 UnicastOrMulticastIpv6Addr::new(addr).unwrap()
2581 }
2582
2583 #[inline]
2584 fn into_addr(self) -> Ipv6Addr {
2585 match self {
2586 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.get(),
2587 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.get(),
2588 }
2589 }
2590}
2591
2592impl UnicastAddress for UnicastOrMulticastIpv6Addr {
2593 fn is_unicast(&self) -> bool {
2594 matches!(self, UnicastOrMulticastIpv6Addr::Unicast(_))
2595 }
2596}
2597
2598impl MulticastAddress for UnicastOrMulticastIpv6Addr {
2599 fn is_multicast(&self) -> bool {
2600 matches!(self, UnicastOrMulticastIpv6Addr::Multicast(_))
2601 }
2602}
2603
2604impl LinkLocalAddress for UnicastOrMulticastIpv6Addr {
2605 fn is_link_local(&self) -> bool {
2606 match self {
2607 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_link_local(),
2608 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_link_local(),
2609 }
2610 }
2611}
2612
2613impl MappedAddress for UnicastOrMulticastIpv6Addr {
2614 fn is_non_mapped(&self) -> bool {
2615 match self {
2616 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_non_mapped(),
2617 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_non_mapped(),
2618 }
2619 }
2620}
2621
2622impl From<UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2623 fn from(addr: UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2624 addr.get()
2625 }
2626}
2627
2628impl From<&'_ UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2629 fn from(addr: &UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2630 addr.get()
2631 }
2632}
2633
2634impl From<UnicastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2635 fn from(addr: UnicastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2636 UnicastOrMulticastIpv6Addr::Unicast(addr)
2637 }
2638}
2639
2640impl From<MulticastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2641 fn from(addr: MulticastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2642 UnicastOrMulticastIpv6Addr::Multicast(addr)
2643 }
2644}
2645
2646impl TryFrom<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2647 type Error = ();
2648 fn try_from(addr: Ipv6Addr) -> Result<UnicastOrMulticastIpv6Addr, ()> {
2649 UnicastOrMulticastIpv6Addr::new(addr).ok_or(())
2650 }
2651}
2652
2653impl AsRef<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2654 fn as_ref(&self) -> &Ipv6Addr {
2655 match self {
2656 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr,
2657 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr,
2658 }
2659 }
2660}
2661
2662impl Deref for UnicastOrMulticastIpv6Addr {
2663 type Target = Ipv6Addr;
2664
2665 fn deref(&self) -> &Ipv6Addr {
2666 self.as_ref()
2667 }
2668}
2669
2670impl Display for UnicastOrMulticastIpv6Addr {
2671 #[inline]
2672 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2673 match self {
2674 UnicastOrMulticastIpv6Addr::Unicast(addr) => write!(f, "{}", addr),
2675 UnicastOrMulticastIpv6Addr::Multicast(addr) => write!(f, "{}", addr),
2676 }
2677 }
2678}
2679
2680impl Debug for UnicastOrMulticastIpv6Addr {
2681 #[inline]
2682 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2683 Display::fmt(self, f)
2684 }
2685}
2686
2687#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2689pub enum SubnetError {
2690 PrefixTooLong,
2693 HostBitsSet,
2696}
2697
2698#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2701pub struct PrefixTooLongError;
2702
2703#[derive(Copy, Clone, Eq, PartialEq, Hash)]
2707pub struct Subnet<A> {
2708 network: A,
2710 prefix: u8,
2711}
2712
2713impl<A: core::cmp::Ord> core::cmp::PartialOrd for Subnet<A> {
2714 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
2715 Some(self.cmp(other))
2716 }
2717}
2718
2719impl<A: core::cmp::Ord> core::cmp::Ord for Subnet<A> {
2721 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
2722 let Self { network, prefix } = self;
2723 let Self { network: other_network, prefix: other_prefix } = other;
2724 match prefix.cmp(other_prefix) {
2725 core::cmp::Ordering::Equal => network.cmp(other_network),
2726 ord => ord,
2727 }
2728 }
2729}
2730
2731impl<A> Subnet<A> {
2732 #[inline]
2742 pub const unsafe fn new_unchecked(network: A, prefix: u8) -> Subnet<A> {
2743 Subnet { network, prefix }
2744 }
2745}
2746
2747impl<A: IpAddress> Subnet<A> {
2748 #[inline]
2755 pub fn new(network: A, prefix: u8) -> Result<Subnet<A>, SubnetError> {
2756 if prefix > A::BYTES * 8 {
2757 return Err(SubnetError::PrefixTooLong);
2758 }
2759 if network != network.mask(prefix) {
2762 return Err(SubnetError::HostBitsSet);
2763 }
2764 Ok(Subnet { network, prefix })
2765 }
2766
2767 #[inline]
2773 pub fn from_host(host: A, prefix: u8) -> Result<Subnet<A>, PrefixTooLongError> {
2774 if prefix > A::BYTES * 8 {
2775 return Err(PrefixTooLongError);
2776 }
2777 let network = host.mask(prefix);
2778 Ok(Subnet { network, prefix })
2779 }
2780
2781 #[inline]
2785 pub fn network(&self) -> A {
2786 self.network
2787 }
2788
2789 #[inline]
2791 pub fn prefix(&self) -> u8 {
2792 self.prefix
2793 }
2794
2795 #[inline]
2801 pub fn contains(&self, addr: &A) -> bool {
2802 self.network == addr.mask(self.prefix)
2803 }
2804}
2805
2806impl Subnet<Ipv4Addr> {
2807 #[inline]
2815 pub fn broadcast(self) -> Ipv4Addr {
2816 if self.prefix == 32 {
2817 self.network
2819 } else {
2820 let mask = <u32>::max_value() >> self.prefix;
2821 Ipv4Addr::new((u32::from_be_bytes(self.network.0) | mask).to_be_bytes())
2822 }
2823 }
2824}
2825
2826impl<A: IpAddress> Display for Subnet<A> {
2827 #[inline]
2828 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2829 write!(f, "{}/{}", self.network, self.prefix)
2830 }
2831}
2832
2833impl<A: IpAddress> Debug for Subnet<A> {
2834 #[inline]
2835 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2836 write!(f, "{}/{}", self.network, self.prefix)
2837 }
2838}
2839
2840impl<A, I: Ip> GenericOverIp<I> for Subnet<A> {
2841 type Type = Subnet<I::Addr>;
2842}
2843
2844#[allow(missing_docs)]
2850#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2851pub enum SubnetEither {
2852 V4(Subnet<Ipv4Addr>),
2853 V6(Subnet<Ipv6Addr>),
2854}
2855
2856impl SubnetEither {
2857 #[inline]
2864 pub fn new(network: IpAddr, prefix: u8) -> Result<SubnetEither, SubnetError> {
2865 Ok(match network {
2866 IpAddr::V4(network) => SubnetEither::V4(Subnet::new(network, prefix)?),
2867 IpAddr::V6(network) => SubnetEither::V6(Subnet::new(network, prefix)?),
2868 })
2869 }
2870
2871 #[inline]
2877 pub fn from_host(host: IpAddr, prefix: u8) -> Result<SubnetEither, PrefixTooLongError> {
2878 Ok(match host {
2879 IpAddr::V4(host) => SubnetEither::V4(Subnet::from_host(host, prefix)?),
2880 IpAddr::V6(host) => SubnetEither::V6(Subnet::from_host(host, prefix)?),
2881 })
2882 }
2883
2884 #[inline]
2886 pub fn net_prefix(&self) -> (IpAddr, u8) {
2887 match self {
2888 SubnetEither::V4(v4) => (v4.network.into(), v4.prefix),
2889 SubnetEither::V6(v6) => (v6.network.into(), v6.prefix),
2890 }
2891 }
2892}
2893
2894impl<A: IpAddress> From<Subnet<A>> for SubnetEither {
2895 fn from(subnet: Subnet<A>) -> SubnetEither {
2896 A::subnet_into_either(subnet)
2897 }
2898}
2899
2900#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2902pub enum AddrSubnetError {
2903 PrefixTooLong,
2906 NotUnicastInSubnet,
2909 InvalidWitness,
2911}
2912
2913#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2924pub struct AddrSubnet<S: IpAddress, A: Witness<S> + Copy = SpecifiedAddr<S>> {
2925 addr: A,
2929 subnet: Subnet<S>,
2930}
2931
2932impl<S: IpAddress, A: Witness<S> + Copy> AddrSubnet<S, A> {
2933 #[inline]
2941 pub fn new(addr: S, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2942 AddrSubnet::from_witness(A::new(addr).ok_or(AddrSubnetError::InvalidWitness)?, prefix)
2943 }
2944
2945 #[inline]
2956 pub unsafe fn new_unchecked(addr: S, prefix: u8) -> Self {
2957 let (subnet, addr) =
2958 unsafe { (Subnet::new_unchecked(addr.mask(prefix), prefix), A::new_unchecked(addr)) };
2959 AddrSubnet { addr, subnet }
2960 }
2961
2962 pub fn from_witness(addr: A, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2971 if prefix > S::BYTES * 8 {
2972 return Err(AddrSubnetError::PrefixTooLong);
2973 }
2974 let subnet = Subnet { network: addr.as_ref().mask(prefix), prefix };
2975 if !addr.as_ref().is_unicast_in_subnet(&subnet) {
2976 return Err(AddrSubnetError::NotUnicastInSubnet);
2977 }
2978 Ok(AddrSubnet { addr, subnet })
2979 }
2980
2981 #[inline]
2983 pub fn subnet(&self) -> Subnet<S> {
2984 self.subnet
2985 }
2986
2987 #[inline]
2989 pub fn addr(&self) -> A {
2990 self.addr
2991 }
2992
2993 #[inline]
2995 pub fn addr_subnet(self) -> (A, Subnet<S>) {
2996 (self.addr, self.subnet)
2997 }
2998
2999 #[inline]
3001 pub fn to_witness<B: Witness<S> + Copy>(&self) -> AddrSubnet<S, B>
3002 where
3003 A: Into<B>,
3004 {
3005 AddrSubnet { addr: self.addr.into(), subnet: self.subnet }
3006 }
3007
3008 #[inline]
3010 pub fn add_witness<B: Witness<A> + Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
3011 let addr = B::new(self.addr)?;
3012 Some(AddrSubnet { addr, subnet: self.subnet })
3013 }
3014
3015 #[inline]
3017 pub fn replace_witness<B: Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
3018 let addr = B::new(self.addr.get())?;
3019 Some(AddrSubnet { addr, subnet: self.subnet })
3020 }
3021}
3022
3023impl<S: IpAddress, A: Witness<S> + Copy + Display> Display for AddrSubnet<S, A> {
3024 #[inline]
3025 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
3026 write!(f, "{}/{}", self.addr, self.subnet.prefix)
3027 }
3028}
3029
3030impl<A: Witness<Ipv6Addr> + Copy> AddrSubnet<Ipv6Addr, A> {
3031 pub fn ipv6_unicast_addr(&self) -> UnicastAddr<Ipv6Addr> {
3037 unsafe { UnicastAddr::new_unchecked(self.addr.get()) }
3038 }
3039
3040 pub fn to_unicast(&self) -> AddrSubnet<Ipv6Addr, UnicastAddr<Ipv6Addr>> {
3046 let AddrSubnet { addr, subnet } = *self;
3047 let addr = unsafe { UnicastAddr::new_unchecked(addr.get()) };
3048 AddrSubnet { addr, subnet }
3049 }
3050}
3051
3052#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, GenericOverIp)]
3054#[generic_over_ip(I, Ip)]
3055pub struct PrefixLength<I: Ip> {
3056 inner: u8,
3058 _ip: IpVersionMarker<I>,
3059}
3060
3061impl<I: Ip> PrefixLength<I> {
3062 pub const fn get(self) -> u8 {
3067 let Self { inner, _ip } = self;
3068 inner
3069 }
3070
3071 pub fn get_mask(self) -> I::Addr {
3073 I::map_ip(
3074 self,
3075 |prefix_len| Ipv4::LIMITED_BROADCAST_ADDRESS.mask(prefix_len.get()),
3076 |prefix_len| Ipv6Addr([u8::MAX; 16]).mask(prefix_len.get()),
3077 )
3078 }
3079
3080 pub const unsafe fn new_unchecked(prefix_length: u8) -> Self {
3087 Self { inner: prefix_length, _ip: I::VERSION_MARKER }
3088 }
3089
3090 pub const fn new(prefix_length: u8) -> Result<Self, PrefixTooLongError> {
3095 if prefix_length > I::Addr::BYTES * 8 {
3096 return Err(PrefixTooLongError);
3097 }
3098 Ok(Self { inner: prefix_length, _ip: I::VERSION_MARKER })
3099 }
3100
3101 pub fn try_from_subnet_mask(subnet_mask: I::Addr) -> Result<Self, NotSubnetMaskError> {
3106 let IpInvariant((count_ones, leading_ones)) = I::map_ip(
3107 subnet_mask,
3108 |subnet_mask| {
3109 let number = u32::from_be_bytes(subnet_mask.ipv4_bytes());
3110 IpInvariant((number.count_ones(), number.leading_ones()))
3111 },
3112 |subnet_mask| {
3113 let number = u128::from_be_bytes(subnet_mask.ipv6_bytes());
3114 IpInvariant((number.count_ones(), number.leading_ones()))
3115 },
3116 );
3117
3118 if leading_ones != count_ones {
3119 return Err(NotSubnetMaskError);
3120 }
3121
3122 Ok(Self {
3123 inner: u8::try_from(leading_ones)
3124 .expect("the number of bits in an IP address fits in u8"),
3125 _ip: IpVersionMarker::default(),
3126 })
3127 }
3128}
3129
3130impl<I: Ip> From<PrefixLength<I>> for u8 {
3131 fn from(value: PrefixLength<I>) -> Self {
3132 value.get()
3133 }
3134}
3135
3136#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3139pub struct NotSubnetMaskError;
3140
3141pub trait IpAddressWitness<A: IpAddress>: Witness<A> {
3154 type IpAddrWitness: IpAddrWitness + From<Self>;
3159}
3160
3161macro_rules! impl_ip_address_witness {
3162 ($witness:ident) => {
3163 impl<A: IpAddress> IpAddressWitness<A> for $witness<A> {
3164 type IpAddrWitness = $witness<IpAddr>;
3165 }
3166 };
3167}
3168
3169impl_ip_address_witness!(SpecifiedAddr);
3170impl_ip_address_witness!(MulticastAddr);
3171impl_ip_address_witness!(LinkLocalAddr);
3172
3173pub trait IpAddrWitness: Witness<IpAddr> + Into<IpAddr<Self::V4, Self::V6>> + Copy {
3187 type V4: Witness<Ipv4Addr> + Into<Self> + Copy;
3192
3193 type V6: Witness<Ipv6Addr> + Into<Self> + Copy;
3198
3199 fn from_v4(addr: Self::V4) -> Self {
3204 addr.into()
3205 }
3206
3207 fn from_v6(addr: Self::V6) -> Self {
3209 addr.into()
3210 }
3211}
3212
3213macro_rules! impl_ip_addr_witness {
3214 ($witness:ident) => {
3215 impl IpAddrWitness for $witness<IpAddr> {
3216 type V4 = $witness<Ipv4Addr>;
3217 type V6 = $witness<Ipv6Addr>;
3218 }
3219 };
3220}
3221
3222impl_ip_addr_witness!(SpecifiedAddr);
3223impl_ip_addr_witness!(MulticastAddr);
3224impl_ip_addr_witness!(LinkLocalAddr);
3225
3226#[allow(missing_docs)]
3233#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
3234pub enum AddrSubnetEither<A: IpAddrWitness = SpecifiedAddr<IpAddr>> {
3235 V4(AddrSubnet<Ipv4Addr, A::V4>),
3236 V6(AddrSubnet<Ipv6Addr, A::V6>),
3237}
3238
3239impl<A: IpAddrWitness> AddrSubnetEither<A> {
3240 #[inline]
3246 pub fn new(addr: IpAddr, prefix: u8) -> Result<AddrSubnetEither<A>, AddrSubnetError> {
3247 Ok(match addr {
3248 IpAddr::V4(addr) => AddrSubnetEither::V4(AddrSubnet::new(addr, prefix)?),
3249 IpAddr::V6(addr) => AddrSubnetEither::V6(AddrSubnet::new(addr, prefix)?),
3250 })
3251 }
3252
3253 #[inline]
3263 pub unsafe fn new_unchecked(addr: IpAddr, prefix: u8) -> Self {
3264 match addr {
3265 IpAddr::V4(addr) => {
3266 AddrSubnetEither::V4(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3267 }
3268 IpAddr::V6(addr) => {
3269 AddrSubnetEither::V6(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3270 }
3271 }
3272 }
3273
3274 pub fn addr(&self) -> A {
3276 match self {
3277 AddrSubnetEither::V4(v4) => v4.addr.into(),
3278 AddrSubnetEither::V6(v6) => v6.addr.into(),
3279 }
3280 }
3281
3282 #[inline]
3284 pub fn addr_prefix(&self) -> (A, u8) {
3285 match self {
3286 AddrSubnetEither::V4(v4) => (v4.addr.into(), v4.subnet.prefix),
3287 AddrSubnetEither::V6(v6) => (v6.addr.into(), v6.subnet.prefix),
3288 }
3289 }
3290
3291 #[inline]
3293 pub fn addr_subnet(&self) -> (A, SubnetEither) {
3294 match self {
3295 AddrSubnetEither::V4(v4) => (v4.addr.into(), SubnetEither::V4(v4.subnet)),
3296 AddrSubnetEither::V6(v6) => (v6.addr.into(), SubnetEither::V6(v6.subnet)),
3297 }
3298 }
3299}
3300
3301impl<S: IpAddress, A: IpAddressWitness<S> + Copy> From<AddrSubnet<S, A>>
3302 for AddrSubnetEither<A::IpAddrWitness>
3303{
3304 #[inline]
3305 fn from(addr_sub: AddrSubnet<S, A>) -> AddrSubnetEither<A::IpAddrWitness> {
3306 let (addr, sub) = addr_sub.addr_subnet();
3307 AddrSubnetEither::new(addr.get().to_ip_addr(), sub.prefix()).unwrap()
3318 }
3319}
3320
3321impl<A> Display for AddrSubnetEither<A>
3322where
3323 A: IpAddrWitness,
3324 A::V4: Display,
3325 A::V6: Display,
3326{
3327 #[inline]
3328 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
3329 match self {
3330 Self::V4(a) => write!(f, "{}", a),
3331 Self::V6(a) => write!(f, "{}", a),
3332 }
3333 }
3334}
3335
3336pub trait GenericOverIp<NewIp: Ip> {
3355 type Type;
3358}
3359
3360pub struct IpInvariant<T>(pub T);
3365
3366impl<T> IpInvariant<T> {
3367 pub fn into_inner(self) -> T {
3369 self.0
3370 }
3371}
3372
3373impl<I: Ip, T> GenericOverIp<I> for IpInvariant<T> {
3374 type Type = Self;
3375}
3376
3377impl<I: Ip> GenericOverIp<I> for core::convert::Infallible {
3378 type Type = Self;
3379}
3380
3381#[derive(GenericOverIp, Default, Debug, PartialOrd, Ord, Eq, PartialEq, Hash)]
3383#[generic_over_ip(I, Ip)]
3384pub struct IpMarked<I: Ip, T> {
3385 inner: T,
3386 _marker: IpVersionMarker<I>,
3387}
3388
3389impl<I: Ip, T> Deref for IpMarked<I, T> {
3390 type Target = T;
3391
3392 fn deref(&self) -> &Self::Target {
3393 self.as_ref()
3394 }
3395}
3396
3397impl<I: Ip, T> DerefMut for IpMarked<I, T> {
3398 fn deref_mut(&mut self) -> &mut Self::Target {
3399 self.as_mut()
3400 }
3401}
3402impl<I: Ip, T> AsRef<T> for IpMarked<I, T> {
3403 fn as_ref(&self) -> &T {
3404 &self.inner
3405 }
3406}
3407
3408impl<I: Ip, T> AsMut<T> for IpMarked<I, T> {
3409 fn as_mut(&mut self) -> &mut T {
3410 &mut self.inner
3411 }
3412}
3413
3414impl<I: Ip, T> IpMarked<I, T> {
3415 pub fn new(inner: T) -> Self {
3417 Self { inner, _marker: IpVersionMarker::<I>::new() }
3418 }
3419
3420 pub fn into_inner(self) -> T {
3422 let Self { inner, _marker } = self;
3423 inner
3424 }
3425
3426 pub fn get(&self) -> &T {
3428 self.as_ref()
3429 }
3430
3431 pub fn get_mut(&mut self) -> &mut T {
3433 self.as_mut()
3434 }
3435}
3436
3437macro_rules! for_each_tuple_ {
3439 ( $m:ident !! ) => ( $m! { });
3440 ( $m:ident !! $h:ident, $($t:ident,)* ) => (
3441 $m! { $h $($t)* }
3442 for_each_tuple_! { $m !! $($t,)* }
3443 );
3444 }
3445
3446macro_rules! for_each_tuple {
3448 ($m:ident) => {
3449 for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, }
3450 };
3451}
3452
3453macro_rules! ip_generic_tuple {
3455 () => {
3456 impl<I: Ip> GenericOverIp<I> for () {
3457 type Type = Self;
3458 }
3459 };
3460 ( $name0:ident $($name:ident)* ) => (
3461 impl<P: Ip, $name0: GenericOverIp<P>, $($name: GenericOverIp<P>,)*>
3462 GenericOverIp<P> for ($name0, $($name,)*) {
3463 type Type = ($name0::Type, $($name::Type,)*);
3464 }
3465 );
3466 }
3467
3468for_each_tuple!(ip_generic_tuple);
3469
3470macro_rules! ip_generic {
3471 ( $type:ident < $($params:ident),* >) => {
3472 impl<IpType: Ip, $($params: GenericOverIp<IpType>),*>
3473 GenericOverIp<IpType> for $type<$($params),*> {
3474 type Type = $type<$($params::Type),*>;
3475 }
3476 };
3477 ( $type:ident) => {
3478 impl<IpType: Ip> GenericOverIp<IpType> for $type {
3479 type Type = Self;
3480 }
3481 }
3482}
3483
3484ip_generic!(bool);
3486ip_generic!(isize);
3487ip_generic!(i8);
3488ip_generic!(i16);
3489ip_generic!(i32);
3490ip_generic!(i64);
3491ip_generic!(usize);
3492ip_generic!(u8);
3493ip_generic!(u16);
3494ip_generic!(u32);
3495ip_generic!(u64);
3496ip_generic!(Option<T>);
3497ip_generic!(Result<R, E>);
3498#[cfg(feature = "std")]
3499ip_generic!(Vec<T>);
3500#[cfg(feature = "std")]
3501ip_generic!(Arc<T>);
3502
3503impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s T
3504where
3505 T::Type: 's,
3506{
3507 type Type = &'s T::Type;
3508}
3509
3510impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s mut T
3511where
3512 T::Type: 's,
3513{
3514 type Type = &'s mut T::Type;
3515}
3516
3517#[cfg(test)]
3518mod tests {
3519 use super::*;
3520 use test_case::test_case;
3521
3522 #[test]
3523 fn test_map_ip_associated_constant() {
3524 fn get_loopback_address<I: Ip>() -> SpecifiedAddr<I::Addr> {
3525 I::map_ip((), |()| Ipv4::LOOPBACK_ADDRESS, |()| Ipv6::LOOPBACK_ADDRESS)
3526 }
3527
3528 assert_eq!(get_loopback_address::<Ipv4>(), Ipv4::LOOPBACK_ADDRESS);
3529 assert_eq!(get_loopback_address::<Ipv6>(), Ipv6::LOOPBACK_ADDRESS);
3530 }
3531
3532 #[test]
3533 fn test_map_ip_different_behavior() {
3534 fn filter_v4<I: Ip>(addr: I::Addr) -> Option<I::Addr> {
3535 I::map_ip(addr, |addr| Some(addr), |_addr| None)
3536 }
3537
3538 assert_eq!(filter_v4::<Ipv4>(*Ipv4::LOOPBACK_ADDRESS), Some(*Ipv4::LOOPBACK_ADDRESS));
3539 assert_eq!(filter_v4::<Ipv6>(*Ipv6::LOOPBACK_ADDRESS), None);
3540 }
3541
3542 #[test]
3543 fn test_map_ip_extension_trait_fn() {
3544 trait FakeIpExt: Ip {
3545 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr;
3546 }
3547
3548 impl FakeIpExt for Ipv4 {
3549 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3550 let Ipv4Addr(mut bytes) = a;
3551 bytes.reverse();
3552 Ipv4Addr(bytes)
3553 }
3554 }
3555 impl FakeIpExt for Ipv6 {
3556 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3557 let Ipv6Addr(mut bytes) = a;
3558 bytes.reverse();
3559 Ipv6Addr(bytes)
3560 }
3561 }
3562
3563 fn reverse_bytes<A: IpAddress>(addr: A) -> A
3564 where
3565 A::Version: FakeIpExt,
3566 {
3567 A::Version::map_ip(addr, Ipv4::reverse_addr_bytes, Ipv6::reverse_addr_bytes)
3568 }
3569
3570 assert_eq!(reverse_bytes(Ipv4Addr([1, 2, 3, 4])), Ipv4Addr([4, 3, 2, 1]));
3571 assert_eq!(
3572 reverse_bytes(Ipv6Addr([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])),
3573 Ipv6Addr([16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
3574 );
3575 }
3576
3577 #[test]
3578 fn test_map_ip_extension_trait_associated_type() {
3579 trait FakeIpExt: Ip {
3580 type PackedInt;
3581 }
3582 impl FakeIpExt for Ipv4 {
3583 type PackedInt = u32;
3584 }
3585 impl FakeIpExt for Ipv6 {
3586 type PackedInt = u128;
3587 }
3588
3589 #[derive(Debug, PartialEq)]
3590 struct Int<T>(T);
3591
3592 impl<T, I: FakeIpExt> GenericOverIp<I> for Int<T> {
3593 type Type = Int<I::PackedInt>;
3594 }
3595
3596 fn from_be_bytes<A: IpAddress>(addr: A) -> Int<<A::Version as FakeIpExt>::PackedInt>
3597 where
3598 A::Version: FakeIpExt,
3599 {
3600 A::Version::map_ip(
3601 addr,
3602 |Ipv4Addr(bytes)| Int(<Ipv4 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3603 |Ipv6Addr(bytes)| Int(<Ipv6 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3604 )
3605 }
3606
3607 assert_eq!(from_be_bytes(Ipv4::LOOPBACK_ADDRESS.get()), Int(0x7f000001u32));
3608 assert_eq!(from_be_bytes(Ipv6::LOOPBACK_ADDRESS.get()), Int(1u128));
3609 }
3610
3611 #[test]
3612 fn map_ip_twice() {
3613 struct FooV4 {
3614 field: Ipv4Addr,
3615 }
3616
3617 impl Default for FooV4 {
3618 fn default() -> Self {
3619 Self { field: Ipv4::UNSPECIFIED_ADDRESS }
3620 }
3621 }
3622
3623 struct FooV6 {
3624 field: Ipv6Addr,
3625 }
3626
3627 impl Default for FooV6 {
3628 fn default() -> Self {
3629 Self { field: Ipv6::UNSPECIFIED_ADDRESS }
3630 }
3631 }
3632
3633 trait IpExt {
3634 type Foo: Default;
3635 }
3636
3637 impl IpExt for Ipv4 {
3638 type Foo = FooV4;
3639 }
3640
3641 impl IpExt for Ipv6 {
3642 type Foo = FooV6;
3643 }
3644
3645 #[derive(GenericOverIp)]
3646 #[generic_over_ip(I, Ip)]
3647 struct Foo<I: IpExt>(I::Foo);
3648
3649 fn do_something<I: Ip + IpExt>(
3650 foo: Foo<I>,
3651 extra_foo: Foo<I>,
3652 captured_foo: Foo<I>,
3653 ) -> I::Addr {
3654 let addr: I::Addr = map_ip_twice!(I, foo, |Foo(foo)| { foo.field });
3655
3656 let _: I::Addr =
3659 map_ip_twice!(<<I as Ip>::Addr as IpAddress>::Version, extra_foo, |Foo(foo)| {
3660 let _: &Foo<I> = &captured_foo;
3664 foo.field
3665 });
3666
3667 addr
3668 }
3669
3670 assert_eq!(
3671 do_something(
3672 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3673 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3674 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS })
3675 ),
3676 Ipv4::UNSPECIFIED_ADDRESS
3677 );
3678 assert_eq!(
3679 do_something(
3680 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3681 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3682 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS })
3683 ),
3684 Ipv6::UNSPECIFIED_ADDRESS
3685 );
3686
3687 fn do_something_with_default_type_alias_shadowing<I: Ip>() -> (I::Addr, IpVersion) {
3688 let (field, IpInvariant(version)) = map_ip_twice!(I, (), |()| {
3689 let foo: Foo<I> = Foo(<I as IpExt>::Foo::default());
3692 (foo.0.field, IpInvariant(I::VERSION))
3693 },);
3694 (field, version)
3695 }
3696
3697 fn do_something_with_type_alias<I: Ip>() -> (I::Addr, IpVersion) {
3698 #[allow(dead_code)]
3701 type IpAlias = usize;
3702
3703 let (field, IpInvariant(version)) = map_ip_twice!(I as IpAlias, (), |()| {
3704 let foo: Foo<IpAlias> = Foo(<IpAlias as IpExt>::Foo::default());
3708 (foo.0.field, IpInvariant(IpAlias::VERSION))
3709 },);
3710 (field, version)
3711 }
3712
3713 assert_eq!(
3714 do_something_with_default_type_alias_shadowing::<Ipv4>(),
3715 (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3716 );
3717 assert_eq!(
3718 do_something_with_default_type_alias_shadowing::<Ipv6>(),
3719 (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3720 );
3721 assert_eq!(
3722 do_something_with_type_alias::<Ipv4>(),
3723 (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3724 );
3725 assert_eq!(
3726 do_something_with_type_alias::<Ipv6>(),
3727 (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3728 );
3729 }
3730
3731 #[test]
3732 fn test_loopback_unicast() {
3733 assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
3737 assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
3738 }
3739
3740 #[test]
3741 fn test_specified() {
3742 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_specified());
3749 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_specified());
3750
3751 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_unicast());
3754
3755 let unicast = Ipv6Addr([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
3756 assert!(unicast.is_unicast());
3757 assert!(unicast.is_specified());
3758
3759 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_multicast());
3762 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_multicast());
3763
3764 let multicast = Ipv4::MULTICAST_SUBNET.network;
3765 assert!(multicast.is_multicast());
3766 assert!(multicast.is_specified());
3767 let multicast = Ipv6::MULTICAST_SUBNET.network;
3768 assert!(multicast.is_multicast());
3769 assert!(multicast.is_specified());
3770
3771 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_link_local());
3774 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_link_local());
3775
3776 let link_local = Ipv4::LINK_LOCAL_UNICAST_SUBNET.network;
3777 assert!(link_local.is_link_local());
3778 assert!(link_local.is_specified());
3779 let link_local = Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network;
3780 assert!(link_local.is_link_local());
3781 assert!(link_local.is_specified());
3782 let link_local = Ipv6::LINK_LOCAL_UNICAST_SUBNET.network;
3783 assert!(link_local.is_link_local());
3784 assert!(link_local.is_specified());
3785 let mut link_local = Ipv6::MULTICAST_SUBNET.network;
3786 link_local.0[1] = 0x02;
3787 assert!(link_local.is_link_local());
3788 assert!(link_local.is_specified());
3789 assert!(Ipv6::LOOPBACK_ADDRESS.is_link_local());
3790 }
3791
3792 #[test]
3793 fn test_link_local() {
3794 assert!(Ipv4::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3796 assert!(Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network.is_link_local());
3797
3798 assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3800 assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_unicast_link_local());
3801 let mut addr = Ipv6::MULTICAST_SUBNET.network;
3802 for flags in 0..=0x0F {
3803 addr.0[1] = (flags << 4) | 0x02;
3805 assert!(addr.is_link_local());
3808 assert!(!addr.is_unicast_link_local());
3809 }
3810
3811 let mut addr = Ipv6::LOOPBACK_ADDRESS.get();
3815 addr.0[1] = 0x02;
3817 assert!(!addr.is_link_local());
3818 }
3819
3820 #[test]
3821 fn test_subnet_new() {
3822 assert_eq!(
3823 Subnet::new(Ipv4Addr::new([255, 255, 255, 255]), 32).unwrap(),
3824 Subnet { network: Ipv4Addr::new([255, 255, 255, 255]), prefix: 32 },
3825 );
3826 assert_eq!(
3828 Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 33),
3829 Err(SubnetError::PrefixTooLong)
3830 );
3831 assert_eq!(
3832 Subnet::from_host(Ipv4Addr::new([255, 255, 255, 255]), 33),
3833 Err(PrefixTooLongError)
3834 );
3835 assert_eq!(Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 8), Err(SubnetError::HostBitsSet));
3837 assert_eq!(
3839 Subnet::from_host(Ipv4Addr::new([255, 255, 0, 0]), 8),
3840 Ok(Subnet { network: Ipv4Addr::new([255, 0, 0, 0]), prefix: 8 })
3841 );
3842
3843 assert_eq!(
3844 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32).unwrap(),
3845 AddrSubnet {
3846 addr: SpecifiedAddr(Ipv4Addr::new([1, 2, 3, 4])),
3847 subnet: Subnet { network: Ipv4Addr::new([1, 2, 3, 4]), prefix: 32 }
3848 }
3849 );
3850 assert!(
3854 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::UNSPECIFIED_ADDRESS, 16)
3855 == Err(AddrSubnetError::InvalidWitness)
3856 );
3857 assert!(
3858 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv6::UNSPECIFIED_ADDRESS, 64)
3859 == Err(AddrSubnetError::InvalidWitness)
3860 );
3861 assert!(
3863 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 33)
3864 == Err(AddrSubnetError::PrefixTooLong)
3865 );
3866 assert!(
3867 AddrSubnet::<_, SpecifiedAddr<_>>::new(
3868 Ipv6Addr::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
3869 129,
3870 ) == Err(AddrSubnetError::PrefixTooLong)
3871 );
3872 assert!(
3874 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::LIMITED_BROADCAST_ADDRESS.get(), 16)
3875 == Err(AddrSubnetError::NotUnicastInSubnet)
3876 );
3877 assert!(
3879 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([192, 168, 255, 255]), 16)
3880 == Err(AddrSubnetError::NotUnicastInSubnet)
3881 );
3882 assert!(
3884 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([224, 0, 0, 1]), 16)
3885 == Err(AddrSubnetError::NotUnicastInSubnet)
3886 );
3887 assert!(
3888 AddrSubnet::<_, SpecifiedAddr<_>>::new(
3889 Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
3890 64,
3891 ) == Err(AddrSubnetError::NotUnicastInSubnet)
3892 );
3893
3894 assert!(
3898 AddrSubnet::<_, LinkLocalAddr<Ipv4Addr>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32)
3899 == Err(AddrSubnetError::InvalidWitness)
3900 );
3901 }
3902
3903 #[test]
3904 fn test_is_unicast_in_subnet() {
3905 let subnet =
3907 Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).expect("1.2.0.0/16 is a valid subnet");
3908 assert!(Ipv4Addr::new([1, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3909 assert!(!Ipv4Addr::new([2, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3910
3911 let subnet =
3912 Subnet::new(Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 64)
3913 .expect("1::/64 is a valid subnet");
3914 assert!(
3915 Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3916 .is_unicast_in_subnet(&subnet)
3917 );
3918 assert!(
3919 !Ipv6Addr::from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3920 .is_unicast_in_subnet(&subnet)
3921 );
3922
3923 assert!(
3925 !Ipv4::UNSPECIFIED_ADDRESS
3926 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 16).unwrap())
3927 );
3928 assert!(
3929 !Ipv6::UNSPECIFIED_ADDRESS
3930 .is_unicast_in_subnet(&Subnet::new(Ipv6::UNSPECIFIED_ADDRESS, 64).unwrap())
3931 );
3932 assert!(
3935 !Ipv4::UNSPECIFIED_ADDRESS
3936 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 31).unwrap())
3937 );
3938 assert!(
3939 !Ipv4::UNSPECIFIED_ADDRESS
3940 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 32).unwrap())
3941 );
3942 assert!(
3944 !Ipv4Addr::new([1, 2, 0, 0])
3945 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap())
3946 );
3947 assert!(
3949 Ipv4Addr::new([1, 2, 3, 0])
3950 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 31).unwrap())
3951 );
3952 assert!(
3953 Ipv4Addr::new([1, 2, 3, 0])
3954 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 32).unwrap())
3955 );
3956 assert!(
3958 !Ipv4::LIMITED_BROADCAST_ADDRESS
3959 .get()
3960 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([128, 0, 0, 0]), 1).unwrap())
3961 );
3962 assert!(
3964 !Ipv4Addr::new([1, 2, 255, 255])
3965 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap())
3966 );
3967 assert!(
3969 Ipv4Addr::new([1, 2, 255, 255])
3970 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 254]), 31).unwrap())
3971 );
3972 assert!(
3973 Ipv4Addr::new([1, 2, 255, 255])
3974 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 255]), 32).unwrap())
3975 );
3976 assert!(!Ipv4Addr::new([224, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::MULTICAST_SUBNET));
3978 assert!(
3979 !Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3980 .is_unicast_in_subnet(&Ipv6::MULTICAST_SUBNET)
3981 );
3982 assert!(!Ipv4Addr::new([240, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::CLASS_E_SUBNET));
3984 }
3985
3986 macro_rules! add_mask_test {
3987 ($name:ident, $addr:ident, $from_ip:expr => {
3988 $($mask:expr => $to_ip:expr),*
3989 }) => {
3990 #[test]
3991 fn $name() {
3992 let from = $addr::from($from_ip);
3993 $(assert_eq!(from.mask($mask), $addr::from($to_ip), "(`{}`.mask({}))", from, $mask);)*
3994 }
3995 };
3996 ($name:ident, $addr:ident, $from_ip:expr => {
3997 $($mask:expr => $to_ip:expr),*,
3998 }) => {
3999 add_mask_test!($name, $addr, $from_ip => { $($mask => $to_ip),* });
4000 };
4001 }
4002
4003 add_mask_test!(v4_full_mask, Ipv4Addr, [255, 254, 253, 252] => {
4004 32 => [255, 254, 253, 252],
4005 28 => [255, 254, 253, 240],
4006 24 => [255, 254, 253, 0],
4007 20 => [255, 254, 240, 0],
4008 16 => [255, 254, 0, 0],
4009 12 => [255, 240, 0, 0],
4010 8 => [255, 0, 0, 0],
4011 4 => [240, 0, 0, 0],
4012 0 => [0, 0, 0, 0],
4013 });
4014
4015 add_mask_test!(v6_full_mask, Ipv6Addr,
4016 [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0] => {
4017 128 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0],
4018 112 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0x00, 0x00],
4019 96 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0x00, 0x00, 0x00, 0x00],
4020 80 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4021 64 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4022 48 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4023 32 => [0xFF, 0xFE, 0xFD, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4024 16 => [0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4025 8 => [0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4026 0 => [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4027 }
4028 );
4029
4030 #[test_case([255, 255, 255, 0] => Ok(24))]
4031 #[test_case([255, 255, 254, 0] => Ok(23))]
4032 #[test_case([255, 255, 253, 0] => Err(NotSubnetMaskError))]
4033 #[test_case([255, 255, 0, 255] => Err(NotSubnetMaskError))]
4034 #[test_case([255, 255, 255, 255] => Ok(32))]
4035 #[test_case([0, 0, 0, 0] => Ok(0))]
4036 #[test_case([0, 0, 0, 255] => Err(NotSubnetMaskError))]
4037 fn test_ipv4_prefix_len_try_from_subnet_mask(
4038 subnet_mask: [u8; 4],
4039 ) -> Result<u8, NotSubnetMaskError> {
4040 let subnet_mask = Ipv4Addr::from(subnet_mask);
4041 PrefixLength::<Ipv4>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
4042 }
4043
4044 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(64))]
4045 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(63))]
4046 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
4047 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 1] => Err(NotSubnetMaskError))]
4048 #[test_case([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(0))]
4049 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] => Ok(128))]
4050 #[test_case([0, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
4051 fn test_ipv6_prefix_len_try_from_subnet_mask(
4052 subnet_mask: [u8; 16],
4053 ) -> Result<u8, NotSubnetMaskError> {
4054 let subnet_mask = Ipv6Addr::from(subnet_mask);
4055 PrefixLength::<Ipv6>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
4056 }
4057
4058 #[test_case(0 => true)]
4059 #[test_case(1 => true)]
4060 #[test_case(32 => true)]
4061 #[test_case(33 => false)]
4062 #[test_case(128 => false)]
4063 #[test_case(129 => false)]
4064 #[test_case(255 => false)]
4065 fn test_ipv4_prefix_len_new(prefix_len: u8) -> bool {
4066 PrefixLength::<Ipv4>::new(prefix_len).is_ok()
4067 }
4068
4069 #[test_case(0 => true)]
4070 #[test_case(1 => true)]
4071 #[test_case(32 => true)]
4072 #[test_case(33 => true)]
4073 #[test_case(128 => true)]
4074 #[test_case(129 => false)]
4075 #[test_case(255 => false)]
4076 fn test_ipv6_prefix_len_new(prefix_len: u8) -> bool {
4077 PrefixLength::<Ipv6>::new(prefix_len).is_ok()
4078 }
4079
4080 #[test_case(0 => [0, 0, 0, 0])]
4081 #[test_case(6 => [252, 0, 0, 0])]
4082 #[test_case(16 => [255, 255, 0, 0])]
4083 #[test_case(25 => [255, 255, 255, 128])]
4084 #[test_case(32 => [255, 255, 255, 255])]
4085 fn test_ipv4_prefix_len_get_mask(prefix_len: u8) -> [u8; 4] {
4086 let Ipv4Addr(inner) = PrefixLength::<Ipv4>::new(prefix_len).unwrap().get_mask();
4087 inner
4088 }
4089
4090 #[test_case(0 => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
4091 #[test_case(6 => [0xFC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
4092 #[test_case(64 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])]
4093 #[test_case(65 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0])]
4094 #[test_case(128 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])]
4095 fn test_ipv6_prefix_len_get_mask(prefix_len: u8) -> [u8; 16] {
4096 let Ipv6Addr(inner) = PrefixLength::<Ipv6>::new(prefix_len).unwrap().get_mask();
4097 inner
4098 }
4099
4100 #[test]
4101 fn test_ipv6_solicited_node() {
4102 let addr = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
4103 let solicited = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
4104 assert_eq!(addr.to_solicited_node_address().get(), solicited);
4105 }
4106
4107 #[test]
4108 fn test_ipv6_address_types() {
4109 assert!(!Ipv6Addr::from([0; 16]).is_specified());
4110 assert!(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1]).is_loopback());
4111 let link_local = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
4112 assert!(link_local.is_link_local());
4113 assert!(link_local.is_valid_unicast());
4114 assert!(link_local.to_solicited_node_address().is_multicast());
4115 let global_unicast = Ipv6Addr::new([0x80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
4116 assert!(global_unicast.is_valid_unicast());
4117 assert!(global_unicast.to_solicited_node_address().is_multicast());
4118
4119 let multi = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
4120 assert!(multi.is_multicast());
4121 assert!(!multi.is_valid_unicast());
4122 }
4123
4124 #[test]
4125 fn test_const_witness() {
4126 assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
4129 assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
4130 assert!(Ipv4::LIMITED_BROADCAST_ADDRESS.0.is_specified());
4131 assert!(Ipv4::ALL_ROUTERS_MULTICAST_ADDRESS.0.is_multicast());
4132 assert!(Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4133 assert!(Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4134 }
4135
4136 #[test]
4137 fn test_ipv6_scope() {
4138 use Ipv6ReservedScope::*;
4139 use Ipv6Scope::*;
4140 use Ipv6UnassignedScope::*;
4141
4142 assert_eq!(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network.scope(), SiteLocal);
4144 assert_eq!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.scope(), LinkLocal);
4145 assert_eq!(Ipv6::UNSPECIFIED_ADDRESS.scope(), Global);
4146
4147 let assert_scope = |value, scope| {
4149 let mut addr = Ipv6::MULTICAST_SUBNET.network;
4150 addr.0[1] |= value;
4152 assert_eq!(addr.scope(), scope);
4153 };
4154 assert_scope(0, Reserved(Scope0));
4155 assert_scope(1, InterfaceLocal);
4156 assert_scope(2, LinkLocal);
4157 assert_scope(3, Reserved(Scope3));
4158 assert_scope(4, AdminLocal);
4159 assert_scope(5, SiteLocal);
4160 assert_scope(6, Unassigned(Scope6));
4161 assert_scope(7, Unassigned(Scope7));
4162 assert_scope(8, OrganizationLocal);
4163 assert_scope(9, Unassigned(Scope9));
4164 assert_scope(0xA, Unassigned(ScopeA));
4165 assert_scope(0xB, Unassigned(ScopeB));
4166 assert_scope(0xC, Unassigned(ScopeC));
4167 assert_scope(0xD, Unassigned(ScopeD));
4168 assert_scope(0xE, Global);
4169 assert_scope(0xF, Reserved(ScopeF));
4170 }
4171
4172 #[test]
4173 fn test_ipv6_multicast_scope_id() {
4174 const ALL_SCOPES: &[Ipv6Scope] = &[
4175 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope0),
4176 Ipv6Scope::InterfaceLocal,
4177 Ipv6Scope::LinkLocal,
4178 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope3),
4179 Ipv6Scope::AdminLocal,
4180 Ipv6Scope::SiteLocal,
4181 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope6),
4182 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope7),
4183 Ipv6Scope::OrganizationLocal,
4184 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope9),
4185 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeA),
4186 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeB),
4187 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeC),
4188 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeD),
4189 Ipv6Scope::Global,
4190 Ipv6Scope::Reserved(Ipv6ReservedScope::ScopeF),
4191 ];
4192 for (i, a) in ALL_SCOPES.iter().enumerate() {
4193 assert_eq!(a.multicast_scope_id(), i.try_into().unwrap());
4194 }
4195 }
4196
4197 #[test]
4198 fn test_ipv4_embedded() {
4199 assert_eq!(
4202 Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_compatible(),
4203 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4])
4204 );
4205 assert_eq!(
4206 Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_mapped().get(),
4207 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]),
4208 );
4209
4210 let compatible = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4]);
4213 let mapped = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]);
4214 let not_embedded = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 1, 2, 3, 4]);
4215 let v4 = Ipv4Addr::new([1, 2, 3, 4]);
4216
4217 assert_eq!(compatible.to_ipv4_compatible(), Some(v4));
4218 assert_eq!(compatible.to_ipv4_mapped(), None);
4219
4220 assert_eq!(mapped.to_ipv4_compatible(), None);
4221 assert_eq!(mapped.to_ipv4_mapped(), Some(v4));
4222
4223 assert_eq!(not_embedded.to_ipv4_compatible(), None);
4224 assert_eq!(not_embedded.to_ipv4_mapped(), None);
4225
4226 assert_eq!(
4227 NonMappedAddr::new(compatible),
4228 Some(unsafe { NonMappedAddr::new_unchecked(compatible) })
4229 );
4230 assert_eq!(NonMappedAddr::new(mapped), None);
4231 assert_eq!(
4232 NonMappedAddr::new(not_embedded),
4233 Some(unsafe { NonMappedAddr::new_unchecked(not_embedded) })
4234 );
4235 assert_eq!(NonMappedAddr::new(v4), Some(unsafe { NonMappedAddr::new_unchecked(v4) }));
4236 }
4237
4238 #[test]
4239 fn test_common_prefix_len_ipv6() {
4240 let ip1 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4241 let ip2 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4242 let ip3 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4243 let ip4 = Ipv6Addr::from([0xFF, 0xFF, 0xC0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4244 let compare_with_ip1 = |target, expect| {
4245 assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4246 };
4247 compare_with_ip1(ip1, 128);
4248 compare_with_ip1(ip2, 0);
4249 compare_with_ip1(ip3, 24);
4250 compare_with_ip1(ip4, 17);
4251 }
4252
4253 #[test]
4254 fn test_common_prefix_len_ipv4() {
4255 let ip1 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0]);
4256 let ip2 = Ipv4Addr::new([0, 0, 0, 0]);
4257 let ip3 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0xFF]);
4258 let ip4 = Ipv4Addr::new([0xFF, 0xFF, 0xC0, 0x20]);
4259 let compare_with_ip1 = |target, expect| {
4260 assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4261 };
4262 compare_with_ip1(ip1, 32);
4263 compare_with_ip1(ip2, 0);
4264 compare_with_ip1(ip3, 24);
4265 compare_with_ip1(ip4, 17);
4266 }
4267
4268 #[test]
4269 fn test_ipv6_display() {
4270 fn test_one(addr: Ipv6Addr, expect: Option<&str>) {
4274 let formatted = format!("{}", addr);
4275 if let Some(expect) = expect {
4276 assert_eq!(formatted, expect);
4277 }
4278
4279 let formatted_std = format!("{}", std::net::Ipv6Addr::from(addr.segments()));
4289 assert_eq!(formatted, formatted_std);
4290 }
4291
4292 test_one(Ipv6::UNSPECIFIED_ADDRESS, Some("::"));
4293 test_one(*Ipv6::LOOPBACK_ADDRESS, Some("::1"));
4294 test_one(Ipv6::MULTICAST_SUBNET.network, Some("ff00::"));
4295 test_one(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network, Some("fe80::"));
4296 test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4297 test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4298 test_one(*Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::2"));
4299 test_one(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network, Some("fec0::"));
4300 test_one(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), Some("1::"));
4301 test_one(Ipv6Addr::new([0, 0, 0, 1, 2, 3, 4, 5]), Some("::1:2:3:4:5"));
4302
4303 for byte in 0u8..=255 {
4308 test_one(
4309 Ipv6Addr::new([
4310 u16::from(byte & 0b1),
4311 u16::from((byte & 0b10) >> 1),
4312 u16::from((byte & 0b100) >> 2),
4313 u16::from((byte & 0b1000) >> 3),
4314 u16::from((byte & 0b10000) >> 4),
4315 u16::from((byte & 0b100000) >> 5),
4316 u16::from((byte & 0b1000000) >> 6),
4317 u16::from((byte & 0b10000000) >> 7),
4318 ]),
4319 None,
4320 );
4321 }
4322 }
4323
4324 #[test_case(Ipv4::UNSPECIFIED_ADDRESS, Ipv4AddressClass::A; "first_class_a")]
4325 #[test_case(Ipv4Addr::new([127, 255, 255, 255]), Ipv4AddressClass::A; "last_class_a")]
4326 #[test_case(Ipv4Addr::new([128, 0, 0, 0]), Ipv4AddressClass::B; "first_class_b")]
4327 #[test_case(Ipv4Addr::new([191, 255, 255, 255]), Ipv4AddressClass::B; "last_class_b")]
4328 #[test_case(Ipv4Addr::new([192, 0, 0, 0]), Ipv4AddressClass::C; "first_class_c")]
4329 #[test_case(Ipv4Addr::new([223, 255, 255, 255]), Ipv4AddressClass::C; "last_class_c")]
4330 #[test_case(Ipv4Addr::new([224, 0, 0, 0]), Ipv4AddressClass::D; "first_class_d")]
4331 #[test_case(Ipv4Addr::new([239, 255, 255, 255]), Ipv4AddressClass::D; "last_class_d")]
4332 #[test_case(Ipv4Addr::new([240, 0, 0, 0]), Ipv4AddressClass::E; "first_class_e")]
4333 #[test_case(Ipv4Addr::new([255, 255, 255, 255]), Ipv4AddressClass::E; "last_class_e")]
4334 fn ipv4addr_class(addr: Ipv4Addr, class: Ipv4AddressClass) {
4335 assert_eq!(addr.class(), class)
4336 }
4337
4338 #[test_case(
4339 Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 24).unwrap(),
4340 Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap()
4341 ; "ipv4_same_prefix")]
4342 #[test_case(
4343 Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap(),
4344 Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 32).unwrap()
4345 ; "ipv4_by_prefix")]
4346 #[test_case(
4347 Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4348 Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap()
4349 ; "ipv6_same_prefix")]
4350 #[test_case(
4351 Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4352 Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 128).unwrap()
4353 ; "ipv6_by_prefix")]
4354 fn subnet_ord<A: core::cmp::Ord>(a: Subnet<A>, b: Subnet<A>) {
4355 assert!(a < b);
4356 }
4357
4358 #[cfg(feature = "std")]
4359 mod std_tests {
4360 use super::*;
4361
4362 #[test]
4363 fn test_conversions() {
4364 let v4 = Ipv4Addr::new([127, 0, 0, 1]);
4365 let v6 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
4366 let std_v4 = net::Ipv4Addr::new(127, 0, 0, 1);
4367 let std_v6 = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
4368
4369 let converted: IpAddr = net::IpAddr::V4(std_v4).into();
4370 assert_eq!(converted, IpAddr::V4(v4));
4371 let converted: IpAddr = net::IpAddr::V6(std_v6).into();
4372 assert_eq!(converted, IpAddr::V6(v6));
4373
4374 let converted: net::IpAddr = IpAddr::V4(v4).into();
4375 assert_eq!(converted, net::IpAddr::V4(std_v4));
4376 let converted: net::IpAddr = IpAddr::V6(v6).into();
4377 assert_eq!(converted, net::IpAddr::V6(std_v6));
4378
4379 let converted: Ipv4Addr = std_v4.into();
4380 assert_eq!(converted, v4);
4381 let converted: Ipv6Addr = std_v6.into();
4382 assert_eq!(converted, v6);
4383
4384 let converted: net::Ipv4Addr = v4.into();
4385 assert_eq!(converted, std_v4);
4386 let converted: net::Ipv6Addr = v6.into();
4387 assert_eq!(converted, std_v6);
4388 }
4389 }
4390}
4391
4392#[cfg(test)]
4394mod macro_test {
4395 use super::*;
4396
4397 fn assert_ip_generic_is<T, I, Other>()
4399 where
4400 I: Ip,
4401 T: GenericOverIp<I, Type = Other>,
4402 {
4403 }
4406
4407 macro_rules! assert_ip_generic {
4408 ($name:ident, Ip $(,$($param:ident),*)?) => {
4409 assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4410 assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4411 assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4412 assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4413 };
4414 ($name:ident, IpAddress $(,$($param:ident),*)?) => {
4415 assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4416 assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4417 assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4418 assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4419 };
4420 ($name:ident $(,$($param:ident),*)?) => {
4421 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4422 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4423 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4424 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4425 };
4426 }
4427
4428 #[test]
4429 fn struct_with_ip_version_parameter() {
4430 #[allow(dead_code)]
4431 #[derive(GenericOverIp)]
4432 #[generic_over_ip(I, Ip)]
4433 struct Generic<I: Ip> {
4434 addr: I::Addr,
4435 }
4436
4437 assert_ip_generic!(Generic, Ip);
4438 }
4439
4440 #[test]
4441 fn struct_with_unbounded_ip_version_parameter() {
4442 #[allow(dead_code)]
4443 #[derive(GenericOverIp)]
4444 #[generic_over_ip(I, Ip)]
4445 struct Generic<I> {
4446 addr: core::marker::PhantomData<I>,
4447 }
4448
4449 assert_ip_generic!(Generic, Ip);
4450 }
4451
4452 #[test]
4453 fn struct_with_ip_address_parameter() {
4454 #[allow(dead_code)]
4455 #[derive(GenericOverIp)]
4456 #[generic_over_ip(A, IpAddress)]
4457 struct Generic<A: IpAddress> {
4458 addr: A,
4459 }
4460
4461 assert_ip_generic!(Generic, IpAddress);
4462 }
4463
4464 #[test]
4465 fn struct_with_unbounded_ip_address_parameter() {
4466 #[allow(dead_code)]
4467 #[derive(GenericOverIp)]
4468 #[generic_over_ip(A, IpAddress)]
4469 struct Generic<A> {
4470 addr: A,
4471 }
4472
4473 assert_ip_generic!(Generic, IpAddress);
4474 }
4475
4476 #[test]
4477 fn struct_with_generic_over_ip_parameter() {
4478 #[derive(GenericOverIp)]
4479 #[generic_over_ip(I, Ip)]
4480 struct InnerGeneric<I: Ip> {
4481 addr: I::Addr,
4482 }
4483
4484 #[derive(GenericOverIp)]
4485 #[generic_over_ip(T, GenericOverIp)]
4486 struct Generic<T> {
4487 foo: T,
4488 }
4489
4490 fn do_something<I: Ip>(g: Generic<InnerGeneric<I>>) {
4491 I::map_ip(
4492 g,
4493 |g| {
4494 let _: Ipv4Addr = g.foo.addr;
4495 },
4496 |g| {
4497 let _: Ipv6Addr = g.foo.addr;
4498 },
4499 )
4500 }
4501
4502 do_something::<Ipv4>(Generic { foo: InnerGeneric { addr: Ipv4::UNSPECIFIED_ADDRESS } });
4503
4504 do_something::<Ipv6>(Generic { foo: InnerGeneric { addr: Ipv6::UNSPECIFIED_ADDRESS } });
4505 }
4506
4507 #[test]
4508 fn enum_with_ip_version_parameter() {
4509 #[allow(dead_code)]
4510 #[derive(GenericOverIp)]
4511 #[generic_over_ip(I, Ip)]
4512 enum Generic<I: Ip> {
4513 A(I::Addr),
4514 B(I::Addr),
4515 }
4516
4517 assert_ip_generic!(Generic, Ip);
4518 }
4519
4520 #[test]
4521 fn enum_with_unbounded_ip_version_parameter() {
4522 #[allow(dead_code)]
4523 #[derive(GenericOverIp)]
4524 #[generic_over_ip(I, Ip)]
4525 enum Generic<I> {
4526 A(core::marker::PhantomData<I>),
4527 B(core::marker::PhantomData<I>),
4528 }
4529
4530 assert_ip_generic!(Generic, Ip);
4531 }
4532
4533 #[test]
4534 fn enum_with_ip_address_parameter() {
4535 #[allow(dead_code)]
4536 #[derive(GenericOverIp)]
4537 #[generic_over_ip(A, IpAddress)]
4538 enum Generic<A: IpAddress> {
4539 A(A),
4540 B(A),
4541 }
4542
4543 assert_ip_generic!(Generic, IpAddress);
4544 }
4545
4546 #[test]
4547 fn enum_with_unbounded_ip_address_parameter() {
4548 #[allow(dead_code)]
4549 #[derive(GenericOverIp)]
4550 #[generic_over_ip(A, IpAddress)]
4551 enum Generic<A> {
4552 A(A),
4553 B(A),
4554 }
4555
4556 assert_ip_generic!(Generic, IpAddress);
4557 }
4558
4559 #[test]
4560 fn struct_with_ip_version_and_other_parameters() {
4561 #[allow(dead_code)]
4562 #[derive(GenericOverIp)]
4563 #[generic_over_ip(I, Ip)]
4564 struct AddrAndDevice<I: Ip, D> {
4565 addr: I::Addr,
4566 device: D,
4567 }
4568 struct Device;
4569
4570 assert_ip_generic!(AddrAndDevice, Ip, Device);
4571 }
4572
4573 #[test]
4574 fn enum_with_ip_version_and_other_parameters() {
4575 #[allow(dead_code)]
4576 #[derive(GenericOverIp)]
4577 #[generic_over_ip(I, Ip)]
4578 enum AddrOrDevice<I: Ip, D> {
4579 Addr(I::Addr),
4580 Device(D),
4581 }
4582 struct Device;
4583
4584 assert_ip_generic!(AddrOrDevice, Ip, Device);
4585 }
4586
4587 #[test]
4588 fn struct_with_ip_address_and_other_parameters() {
4589 #[allow(dead_code)]
4590 #[derive(GenericOverIp)]
4591 #[generic_over_ip(A, IpAddress)]
4592 struct AddrAndDevice<A: IpAddress, D> {
4593 addr: A,
4594 device: D,
4595 }
4596 struct Device;
4597
4598 assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4599 }
4600
4601 #[test]
4602 fn struct_with_unbounded_ip_address_and_other_parameters() {
4603 #[allow(dead_code)]
4604 #[derive(GenericOverIp)]
4605 #[generic_over_ip(A, IpAddress)]
4606 struct AddrAndDevice<A, D> {
4607 addr: A,
4608 device: D,
4609 }
4610 struct Device;
4611
4612 assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4613 }
4614
4615 #[test]
4616 fn enum_with_ip_address_and_other_parameters() {
4617 #[allow(dead_code)]
4618 #[derive(GenericOverIp, Debug, PartialEq)]
4619 #[generic_over_ip(A, IpAddress)]
4620 enum AddrOrDevice<A: IpAddress, D> {
4621 Addr(A),
4622 Device(D),
4623 }
4624 struct Device;
4625
4626 assert_ip_generic!(AddrOrDevice, IpAddress, Device);
4627 }
4628
4629 #[test]
4630 fn struct_invariant_over_ip() {
4631 #[allow(dead_code)]
4632 #[derive(GenericOverIp)]
4633 #[generic_over_ip()]
4634 struct Invariant(usize);
4635
4636 assert_ip_generic!(Invariant);
4637 }
4638
4639 #[test]
4640 fn enum_invariant_over_ip() {
4641 #[allow(dead_code)]
4642 #[derive(GenericOverIp)]
4643 #[generic_over_ip()]
4644 enum Invariant {
4645 Usize(usize),
4646 }
4647
4648 assert_ip_generic!(Invariant);
4649 }
4650
4651 #[test]
4652 fn struct_invariant_over_ip_with_other_params() {
4653 #[allow(dead_code)]
4654 #[derive(GenericOverIp)]
4655 #[generic_over_ip()]
4656 struct Invariant<B, C, D>(B, C, D);
4657
4658 assert_ip_generic!(Invariant, usize, bool, char);
4659 }
4660
4661 #[test]
4662 fn enum_invariant_over_ip_with_other_params() {
4663 #[allow(dead_code)]
4664 #[derive(GenericOverIp)]
4665 #[generic_over_ip()]
4666 enum Invariant<A, B, C> {
4667 A(A),
4668 B(B),
4669 C(C),
4670 }
4671
4672 assert_ip_generic!(Invariant, usize, bool, char);
4673 }
4674
4675 #[test]
4676 fn struct_with_ip_version_extension_parameter() {
4677 trait FakeIpExt: Ip {
4678 type Associated;
4679 }
4680 impl FakeIpExt for Ipv4 {
4681 type Associated = u8;
4682 }
4683 impl FakeIpExt for Ipv6 {
4684 type Associated = u16;
4685 }
4686
4687 #[allow(dead_code)]
4688 #[derive(GenericOverIp)]
4689 #[generic_over_ip(I, Ip)]
4690 struct Generic<I: FakeIpExt> {
4691 field: I::Associated,
4692 }
4693
4694 assert_ip_generic!(Generic, Ip);
4695 }
4696
4697 #[test]
4698 fn struct_with_ip_version_extension_parameter_but_no_ip_bound() {
4699 trait FakeIpExt: Ip {
4700 type Associated;
4701 }
4702 impl FakeIpExt for Ipv4 {
4703 type Associated = u8;
4704 }
4705 impl FakeIpExt for Ipv6 {
4706 type Associated = u16;
4707 }
4708
4709 #[allow(dead_code)]
4710 #[derive(GenericOverIp)]
4711 #[generic_over_ip(I, Ip)]
4712 struct Generic<I: FakeIpExt> {
4713 field: I::Associated,
4714 }
4715
4716 assert_ip_generic!(Generic, Ip);
4717 }
4718
4719 #[test]
4720 fn struct_with_ip_address_extension_parameter() {
4721 trait FakeIpAddressExt: IpAddress {
4722 type Associated;
4723 }
4724 impl FakeIpAddressExt for Ipv4Addr {
4725 type Associated = u8;
4726 }
4727 impl FakeIpAddressExt for Ipv6Addr {
4728 type Associated = u16;
4729 }
4730
4731 #[allow(dead_code)]
4732 #[derive(GenericOverIp)]
4733 #[generic_over_ip(A, IpAddress)]
4734 struct Generic<A: IpAddress + FakeIpAddressExt> {
4735 field: A::Associated,
4736 }
4737
4738 assert_ip_generic!(Generic, IpAddress);
4739 }
4740
4741 #[test]
4742 fn type_with_lifetime_and_ip_parameter() {
4743 #[allow(dead_code)]
4744 #[derive(GenericOverIp)]
4745 #[generic_over_ip(I, Ip)]
4746 struct Generic<'a, I: Ip> {
4747 field: &'a I::Addr,
4748 }
4749
4750 assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv4, Generic<'static, Ipv4>>();
4751 assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv6, Generic<'static, Ipv6>>();
4752 assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv4, Generic<'static, Ipv4>>();
4753 assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv6, Generic<'static, Ipv6>>();
4754 }
4755
4756 #[test]
4757 fn type_with_lifetime_and_no_ip_parameter() {
4758 #[allow(dead_code)]
4759 #[derive(GenericOverIp)]
4760 #[generic_over_ip()]
4761 struct Generic<'a> {
4762 field: &'a (),
4763 }
4764
4765 assert_ip_generic_is::<Generic<'static>, Ipv4, Generic<'static>>();
4766 assert_ip_generic_is::<Generic<'static>, Ipv6, Generic<'static>>();
4767 }
4768
4769 #[test]
4770 fn type_with_params_list_with_trailing_comma() {
4771 trait IpExtensionTraitWithVeryLongName {}
4772 trait OtherIpExtensionTraitWithVeryLongName {}
4773 trait LongNameToForceFormatterToBreakLineAndAddTrailingComma {}
4774 #[allow(dead_code)]
4776 #[derive(GenericOverIp)]
4777 #[generic_over_ip(I, Ip)]
4778 struct Generic<
4779 I: Ip
4780 + IpExtensionTraitWithVeryLongName
4781 + OtherIpExtensionTraitWithVeryLongName
4782 + LongNameToForceFormatterToBreakLineAndAddTrailingComma,
4783 > {
4784 field: I::Addr,
4785 }
4786 }
4787}