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
66pub use net_types_macros::GenericOverIp;
67use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
68
69use crate::{
70 sealed, LinkLocalAddr, LinkLocalAddress, MappedAddress, MulticastAddr, MulticastAddress,
71 NonMappedAddr, Scope, ScopeableAddress, SpecifiedAddr, SpecifiedAddress, UnicastAddr,
72 UnicastAddress, Witness,
73};
74
75#[allow(missing_docs)]
82#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
83pub enum IpVersion {
84 V4,
85 V6,
86}
87
88#[macro_export]
101macro_rules! for_any_ip_version {
102 ($ip_version:expr, $type_param:ident, $expression:expr) => {
103 match $ip_version {
104 $crate::ip::IpVersion::V4 => {
105 type $type_param = $crate::ip::Ipv4;
106 $expression
107 }
108 $crate::ip::IpVersion::V6 => {
109 type $type_param = $crate::ip::Ipv6;
110 $expression
111 }
112 }
113 };
114}
115
116#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, GenericOverIp)]
124#[generic_over_ip(I, Ip)]
125pub struct IpVersionMarker<I: Ip> {
126 _marker: core::marker::PhantomData<I>,
127}
128
129impl<I: Ip> IpVersionMarker<I> {
130 pub const fn new() -> Self {
134 Self { _marker: core::marker::PhantomData }
135 }
136}
137
138impl<I: Ip> Default for IpVersionMarker<I> {
139 fn default() -> Self {
140 Self { _marker: core::marker::PhantomData }
141 }
142}
143
144impl<I: Ip> Debug for IpVersionMarker<I> {
145 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
146 write!(f, "IpVersionMarker<{}>", I::NAME)
147 }
148}
149
150#[allow(missing_docs)]
159#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
160pub enum IpAddr<V4 = Ipv4Addr, V6 = Ipv6Addr> {
161 V4(V4),
162 V6(V6),
163}
164
165impl<V4: Display, V6: Display> Display for IpAddr<V4, V6> {
166 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
167 match self {
168 Self::V4(v4) => v4.fmt(f),
169 Self::V6(v6) => v6.fmt(f),
170 }
171 }
172}
173
174impl<V4, V6> IpAddr<V4, V6> {
175 pub fn transpose<W: IpAddrWitness<V4 = V4, V6 = V6>>(self) -> W {
182 match self {
183 IpAddr::V4(addr) => W::from_v4(addr),
184 IpAddr::V6(addr) => W::from_v6(addr),
185 }
186 }
187}
188
189impl<A: IpAddress> From<A> for IpAddr {
190 #[inline]
191 fn from(addr: A) -> IpAddr {
192 addr.to_ip_addr()
193 }
194}
195
196impl<A: IpAddress, const N: usize> From<[A; N]> for IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
197 #[inline]
198 fn from(addrs: [A; N]) -> Self {
199 A::array_into_ip_addr(addrs)
200 }
201}
202
203#[cfg(feature = "std")]
204impl From<net::IpAddr> for IpAddr {
205 #[inline]
206 fn from(addr: net::IpAddr) -> IpAddr {
207 match addr {
208 net::IpAddr::V4(addr) => IpAddr::V4(addr.into()),
209 net::IpAddr::V6(addr) => IpAddr::V6(addr.into()),
210 }
211 }
212}
213
214#[cfg(feature = "std")]
215impl From<IpAddr> for net::IpAddr {
216 fn from(addr: IpAddr) -> net::IpAddr {
217 match addr {
218 IpAddr::V4(addr) => net::IpAddr::V4(addr.into()),
219 IpAddr::V6(addr) => net::IpAddr::V6(addr.into()),
220 }
221 }
222}
223
224impl IpVersion {
225 #[inline]
229 pub fn version_number(self) -> u8 {
230 match self {
231 IpVersion::V4 => 4,
232 IpVersion::V6 => 6,
233 }
234 }
235
236 #[inline]
238 pub fn is_v4(self) -> bool {
239 self == IpVersion::V4
240 }
241
242 #[inline]
244 pub fn is_v6(self) -> bool {
245 self == IpVersion::V6
246 }
247}
248
249#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
252pub struct Mtu(u32);
253
254impl Mtu {
255 pub const fn new(mtu: u32) -> Self {
257 Self(mtu)
258 }
259
260 pub const fn get(&self) -> u32 {
262 let Self(mtu) = self;
263 *mtu
264 }
265
266 pub const fn max() -> Self {
268 Self(u32::MAX)
269 }
270
271 pub const fn no_limit() -> Self {
275 Self::max()
276 }
277}
278
279impl From<Mtu> for u32 {
280 fn from(Mtu(mtu): Mtu) -> Self {
281 mtu
282 }
283}
284
285impl From<Mtu> for usize {
286 fn from(Mtu(mtu): Mtu) -> Self {
287 mtu.try_into().expect("mtu must fit usize")
288 }
289}
290
291pub trait Ip:
306 Sized
307 + Clone
308 + Copy
309 + Debug
310 + Default
311 + Eq
312 + Hash
313 + Ord
314 + PartialEq
315 + PartialOrd
316 + Send
317 + Sync
318 + sealed::Sealed
319 + 'static
320{
321 const VERSION: IpVersion;
325
326 const VERSION_MARKER: IpVersionMarker<Self>;
328
329 const UNSPECIFIED_ADDRESS: Self::Addr;
333
334 const LOOPBACK_ADDRESS: SpecifiedAddr<Self::Addr>;
341
342 const LOOPBACK_SUBNET: Subnet<Self::Addr>;
347
348 const MULTICAST_SUBNET: Subnet<Self::Addr>;
350
351 const LINK_LOCAL_UNICAST_SUBNET: Subnet<Self::Addr>;
361
362 const NAME: &'static str;
364
365 const MINIMUM_LINK_MTU: Mtu;
372
373 type Addr: IpAddress<Version = Self>
377 + GenericOverIp<Self, Type = Self::Addr>
378 + GenericOverIp<Ipv4, Type = Ipv4Addr>
379 + GenericOverIp<Ipv6, Type = Ipv6Addr>;
380
381 fn map_ip<
412 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
413 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
414 >(
415 input: In,
416 v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
417 v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
418 ) -> Out;
419
420 fn map_ip_in<
427 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
428 Out,
429 >(
430 input: In,
431 v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> Out,
432 v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> Out,
433 ) -> Out {
434 Self::map_ip::<_, IpInvariant<_>>(
435 input,
436 |input| IpInvariant(v4(input)),
437 |input| IpInvariant(v6(input)),
438 )
439 .into_inner()
440 }
441
442 fn map_ip_out<
449 In,
450 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
451 >(
452 input: In,
453 v4: impl FnOnce(In) -> <Out as GenericOverIp<Ipv4>>::Type,
454 v6: impl FnOnce(In) -> <Out as GenericOverIp<Ipv6>>::Type,
455 ) -> Out {
456 Self::map_ip(
457 IpInvariant(input),
458 |IpInvariant(input)| v4(input),
459 |IpInvariant(input)| v6(input),
460 )
461 }
462}
463
464#[macro_export]
533macro_rules! map_ip_twice {
534 ($ip:ident, $input:expr, $fn:expr $(,)?) => {
538 $crate::map_ip_twice!($ip as $ip, $input, $fn)
539 };
540 ($ip:ty, $input:expr, $fn:expr $(,)?) => {
544 <$ip as $crate::ip::Ip>::map_ip($input, { $fn }, { $fn })
545 };
546 ($ip:ty as $iptypealias:ident, $input:expr, $fn:expr $(,)?) => {
547 <$ip as $crate::ip::Ip>::map_ip(
548 $input,
549 {
550 #[allow(dead_code)]
551 type $iptypealias = $crate::ip::Ipv4;
552 $fn
553 },
554 {
555 #[allow(dead_code)]
556 type $iptypealias = $crate::ip::Ipv6;
557 $fn
558 },
559 )
560 };
561}
562
563#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
570pub enum Ipv4 {}
571
572impl Default for Ipv4 {
573 fn default() -> Ipv4 {
574 panic!("Ipv4 default")
575 }
576}
577
578impl sealed::Sealed for Ipv4 {}
579
580impl Ip for Ipv4 {
581 const VERSION: IpVersion = IpVersion::V4;
582 const VERSION_MARKER: IpVersionMarker<Self> = IpVersionMarker::new();
583
584 const UNSPECIFIED_ADDRESS: Ipv4Addr = Ipv4Addr::new([0, 0, 0, 0]);
587 const LOOPBACK_ADDRESS: SpecifiedAddr<Ipv4Addr> =
596 unsafe { SpecifiedAddr::new_unchecked(Ipv4Addr::new([127, 0, 0, 1])) };
597 const LOOPBACK_SUBNET: Subnet<Ipv4Addr> =
601 Subnet { network: Ipv4Addr::new([127, 0, 0, 0]), prefix: 8 };
602 const MULTICAST_SUBNET: Subnet<Ipv4Addr> = Self::CLASS_D_SUBNET;
606 const LINK_LOCAL_UNICAST_SUBNET: Subnet<Ipv4Addr> =
611 Subnet { network: Ipv4Addr::new([169, 254, 0, 0]), prefix: 16 };
612 const NAME: &'static str = "IPv4";
613 const MINIMUM_LINK_MTU: Mtu = Mtu(68);
620 type Addr = Ipv4Addr;
621
622 fn map_ip<
623 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
624 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
625 >(
626 input: In,
627 v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
628 _v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
629 ) -> Out {
630 v4(input)
631 }
632}
633
634impl Ipv4 {
635 pub const LIMITED_BROADCAST_ADDRESS: SpecifiedAddr<Ipv4Addr> =
645 unsafe { SpecifiedAddr::new_unchecked(Ipv4Addr::new([255, 255, 255, 255])) };
646
647 pub const CLASS_A_SUBNET: Subnet<Ipv4Addr> =
653 Subnet { network: Ipv4Addr::new([0, 0, 0, 0]), prefix: 1 };
654
655 pub const CLASS_B_SUBNET: Subnet<Ipv4Addr> =
661 Subnet { network: Ipv4Addr::new([128, 0, 0, 0]), prefix: 2 };
662
663 pub const CLASS_C_SUBNET: Subnet<Ipv4Addr> =
669 Subnet { network: Ipv4Addr::new([192, 0, 0, 0]), prefix: 3 };
670
671 pub const CLASS_D_SUBNET: Subnet<Ipv4Addr> =
679 Subnet { network: Ipv4Addr::new([224, 0, 0, 0]), prefix: 4 };
680
681 pub const CLASS_E_SUBNET: Subnet<Ipv4Addr> =
691 Subnet { network: Ipv4Addr::new([240, 0, 0, 0]), prefix: 4 };
692
693 pub const LINK_LOCAL_MULTICAST_SUBNET: Subnet<Ipv4Addr> =
698 Subnet { network: Ipv4Addr::new([224, 0, 0, 0]), prefix: 24 };
699
700 pub const ALL_SYSTEMS_MULTICAST_ADDRESS: MulticastAddr<Ipv4Addr> =
705 unsafe { MulticastAddr::new_unchecked(Ipv4Addr::new([224, 0, 0, 1])) };
706
707 pub const ALL_ROUTERS_MULTICAST_ADDRESS: MulticastAddr<Ipv4Addr> =
712 unsafe { MulticastAddr::new_unchecked(Ipv4Addr::new([224, 0, 0, 2])) };
713}
714
715#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
722pub enum Ipv6 {}
723
724impl Default for Ipv6 {
725 fn default() -> Ipv6 {
726 panic!("Ipv6 default")
727 }
728}
729
730impl sealed::Sealed for Ipv6 {}
731
732impl Ip for Ipv6 {
733 const VERSION: IpVersion = IpVersion::V6;
734 const VERSION_MARKER: IpVersionMarker<Self> = IpVersionMarker::new();
735 const UNSPECIFIED_ADDRESS: Ipv6Addr = Ipv6Addr::new([0; 8]);
751 const LOOPBACK_ADDRESS: SpecifiedAddr<Ipv6Addr> =
771 unsafe { SpecifiedAddr::new_unchecked(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1])) };
772 const LOOPBACK_SUBNET: Subnet<Ipv6Addr> =
780 Subnet { network: Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1]), prefix: 128 };
781 const MULTICAST_SUBNET: Subnet<Ipv6Addr> =
786 Subnet { network: Ipv6Addr::new([0xff00, 0, 0, 0, 0, 0, 0, 0]), prefix: 8 };
787 const LINK_LOCAL_UNICAST_SUBNET: Subnet<Ipv6Addr> =
797 Subnet { network: Ipv6Addr::new([0xfe80, 0, 0, 0, 0, 0, 0, 0]), prefix: 10 };
798 const NAME: &'static str = "IPv6";
799 const MINIMUM_LINK_MTU: Mtu = Mtu(1280);
811 type Addr = Ipv6Addr;
812
813 fn map_ip<
814 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
815 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
816 >(
817 input: In,
818 _v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
819 v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
820 ) -> Out {
821 v6(input)
822 }
823}
824
825impl Ipv6 {
826 pub const LOOPBACK_IPV6_ADDRESS: UnicastAddr<Ipv6Addr> =
833 unsafe { UnicastAddr::new_unchecked(Ipv6::LOOPBACK_ADDRESS.0) };
834
835 pub const ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS: MulticastAddr<Ipv6Addr> =
840 unsafe { MulticastAddr::new_unchecked(Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0, 0, 1])) };
841
842 pub const ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS: MulticastAddr<Ipv6Addr> =
847 unsafe { MulticastAddr::new_unchecked(Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0, 0, 2])) };
848
849 pub const SITE_LOCAL_UNICAST_SUBNET: Subnet<Ipv6Addr> =
863 Subnet { network: Ipv6Addr::new([0xfec0, 0, 0, 0, 0, 0, 0, 0]), prefix: 10 };
864
865 pub const UNICAST_INTERFACE_IDENTIFIER_BITS: u8 = 64;
890
891 pub const FLOW_LABEL_BITS: u8 = 20;
895}
896
897pub trait IpAddress:
904 Sized
905 + Eq
906 + PartialEq
907 + PartialOrd
908 + Ord
909 + Hash
910 + Copy
911 + Display
912 + Debug
913 + Default
914 + Sync
915 + Send
916 + LinkLocalAddress
917 + ScopeableAddress
918 + GenericOverIp<Self::Version, Type = Self>
919 + GenericOverIp<Ipv4, Type = Ipv4Addr>
920 + GenericOverIp<Ipv6, Type = Ipv6Addr>
921 + sealed::Sealed
922 + 'static
923{
924 const BYTES: u8;
928
929 type Version: Ip<Addr = Self>;
933
934 fn bytes(&self) -> &[u8];
936
937 fn mask(&self, bits: u8) -> Self;
947
948 fn to_ip_addr(&self) -> IpAddr;
950
951 #[inline]
958 fn is_loopback(&self) -> bool {
959 Self::Version::LOOPBACK_SUBNET.contains(self)
960 }
961
962 fn common_prefix_len(&self, other: &Self) -> u8;
964
965 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool;
1025
1026 #[doc(hidden)]
1032 fn subnet_into_either(subnet: Subnet<Self>) -> SubnetEither;
1033
1034 #[doc(hidden)]
1035 fn array_into_ip_addr<const N: usize>(addrs: [Self; N])
1036 -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]>;
1037}
1038
1039impl<A: IpAddress> SpecifiedAddress for A {
1040 #[inline]
1047 fn is_specified(&self) -> bool {
1048 self != &A::Version::UNSPECIFIED_ADDRESS
1049 }
1050}
1051
1052macro_rules! map_ip_addr {
1055 ($val:expr, $method:ident) => {
1056 match $val {
1057 IpAddr::V4(a) => a.$method(),
1058 IpAddr::V6(a) => a.$method(),
1059 }
1060 };
1061}
1062
1063impl SpecifiedAddress for IpAddr {
1064 #[inline]
1069 fn is_specified(&self) -> bool {
1070 map_ip_addr!(self, is_specified)
1071 }
1072}
1073
1074impl<A: IpAddress> MulticastAddress for A {
1075 #[inline]
1082 fn is_multicast(&self) -> bool {
1083 <A as IpAddress>::Version::MULTICAST_SUBNET.contains(self)
1084 }
1085}
1086
1087impl MulticastAddress for IpAddr {
1088 #[inline]
1093 fn is_multicast(&self) -> bool {
1094 map_ip_addr!(self, is_multicast)
1095 }
1096}
1097
1098impl LinkLocalAddress for Ipv4Addr {
1099 #[inline]
1105 fn is_link_local(&self) -> bool {
1106 Ipv4::LINK_LOCAL_UNICAST_SUBNET.contains(self)
1107 || Ipv4::LINK_LOCAL_MULTICAST_SUBNET.contains(self)
1108 }
1109}
1110
1111impl LinkLocalAddress for Ipv6Addr {
1112 #[inline]
1122 fn is_link_local(&self) -> bool {
1123 Ipv6::LINK_LOCAL_UNICAST_SUBNET.contains(self)
1124 || (self.is_multicast() && self.scope() == Ipv6Scope::LinkLocal)
1125 || self == Ipv6::LOOPBACK_ADDRESS.deref()
1126 }
1127}
1128
1129impl LinkLocalAddress for IpAddr {
1130 #[inline]
1132 fn is_link_local(&self) -> bool {
1133 map_ip_addr!(self, is_link_local)
1134 }
1135}
1136
1137impl<A: IpAddress> MappedAddress for A {
1138 #[inline]
1149 fn is_non_mapped(&self) -> bool {
1150 A::Version::map_ip(self, |_addr_v4| true, |addr_v6| addr_v6.to_ipv4_mapped().is_none())
1151 }
1152}
1153
1154impl MappedAddress for IpAddr {
1155 #[inline]
1157 fn is_non_mapped(&self) -> bool {
1158 map_ip_addr!(self, is_non_mapped)
1159 }
1160}
1161
1162impl<I: Ip> GenericOverIp<I> for Ipv4Addr {
1163 type Type = I::Addr;
1164}
1165
1166impl<I: Ip> GenericOverIp<I> for Ipv6Addr {
1167 type Type = I::Addr;
1168}
1169
1170impl ScopeableAddress for Ipv4Addr {
1171 type Scope = ();
1172
1173 fn scope(&self) {}
1178}
1179
1180#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1186pub enum Ipv6Scope {
1187 InterfaceLocal,
1189 LinkLocal,
1191 AdminLocal,
1193 SiteLocal,
1209 OrganizationLocal,
1211 Global,
1213 Reserved(Ipv6ReservedScope),
1217 Unassigned(Ipv6UnassignedScope),
1219}
1220
1221#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1226pub enum Ipv6ReservedScope {
1227 Scope0 = 0,
1229 Scope3 = 3,
1231 ScopeF = 0xF,
1233}
1234
1235#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1238pub enum Ipv6UnassignedScope {
1239 Scope6 = 6,
1241 Scope7 = 7,
1243 Scope9 = 9,
1245 ScopeA = 0xA,
1247 ScopeB = 0xB,
1249 ScopeC = 0xC,
1251 ScopeD = 0xD,
1253}
1254
1255impl Scope for Ipv6Scope {
1256 #[inline]
1257 fn can_have_zone(&self) -> bool {
1258 matches!(self, Ipv6Scope::LinkLocal)
1278 }
1279}
1280
1281impl Ipv6Scope {
1282 pub const MULTICAST_SCOPE_ID_INTERFACE_LOCAL: u8 = 1;
1287
1288 pub const MULTICAST_SCOPE_ID_LINK_LOCAL: u8 = 2;
1293
1294 pub const MULTICAST_SCOPE_ID_ADMIN_LOCAL: u8 = 4;
1299
1300 pub const MULTICAST_SCOPE_ID_SITE_LOCAL: u8 = 5;
1307
1308 pub const MULTICAST_SCOPE_ID_ORG_LOCAL: u8 = 8;
1313
1314 pub const MULTICAST_SCOPE_ID_GLOBAL: u8 = 0xE;
1319
1320 pub fn multicast_scope_id(&self) -> u8 {
1338 match self {
1339 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope0) => 0,
1340 Ipv6Scope::InterfaceLocal => Self::MULTICAST_SCOPE_ID_INTERFACE_LOCAL,
1341 Ipv6Scope::LinkLocal => Self::MULTICAST_SCOPE_ID_LINK_LOCAL,
1342 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope3) => 3,
1343 Ipv6Scope::AdminLocal => Self::MULTICAST_SCOPE_ID_ADMIN_LOCAL,
1344 Ipv6Scope::SiteLocal => Self::MULTICAST_SCOPE_ID_SITE_LOCAL,
1345 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope6) => 6,
1346 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope7) => 7,
1347 Ipv6Scope::OrganizationLocal => Self::MULTICAST_SCOPE_ID_ORG_LOCAL,
1348 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope9) => 9,
1349 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeA) => 0xA,
1350 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeB) => 0xB,
1351 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeC) => 0xC,
1352 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeD) => 0xD,
1353 Ipv6Scope::Global => Self::MULTICAST_SCOPE_ID_GLOBAL,
1354 Ipv6Scope::Reserved(Ipv6ReservedScope::ScopeF) => 0xF,
1355 }
1356 }
1357}
1358
1359impl ScopeableAddress for Ipv6Addr {
1360 type Scope = Ipv6Scope;
1361
1362 #[inline]
1364 fn scope(&self) -> Ipv6Scope {
1365 if self.is_multicast() {
1366 use Ipv6ReservedScope::*;
1367 use Ipv6Scope::*;
1368 use Ipv6UnassignedScope::*;
1369
1370 match self.0[1] & 0xF {
1374 0 => Reserved(Scope0),
1375 Ipv6Scope::MULTICAST_SCOPE_ID_INTERFACE_LOCAL => InterfaceLocal,
1376 Ipv6Scope::MULTICAST_SCOPE_ID_LINK_LOCAL => LinkLocal,
1377 3 => Reserved(Scope3),
1378 Ipv6Scope::MULTICAST_SCOPE_ID_ADMIN_LOCAL => AdminLocal,
1379 Ipv6Scope::MULTICAST_SCOPE_ID_SITE_LOCAL => SiteLocal,
1380 6 => Unassigned(Scope6),
1381 7 => Unassigned(Scope7),
1382 Ipv6Scope::MULTICAST_SCOPE_ID_ORG_LOCAL => OrganizationLocal,
1383 9 => Unassigned(Scope9),
1384 0xA => Unassigned(ScopeA),
1385 0xB => Unassigned(ScopeB),
1386 0xC => Unassigned(ScopeC),
1387 0xD => Unassigned(ScopeD),
1388 Ipv6Scope::MULTICAST_SCOPE_ID_GLOBAL => Global,
1389 0xF => Reserved(ScopeF),
1390 _ => unreachable!(),
1391 }
1392 } else if self.is_link_local() {
1393 Ipv6Scope::LinkLocal
1394 } else if self.is_site_local() {
1395 Ipv6Scope::SiteLocal
1396 } else {
1397 Ipv6Scope::Global
1398 }
1399 }
1400}
1401
1402impl Scope for IpAddr<(), Ipv6Scope> {
1403 #[inline]
1404 fn can_have_zone(&self) -> bool {
1405 match self {
1406 IpAddr::V4(scope) => scope.can_have_zone(),
1407 IpAddr::V6(scope) => scope.can_have_zone(),
1408 }
1409 }
1410}
1411
1412impl ScopeableAddress for IpAddr {
1413 type Scope = IpAddr<(), Ipv6Scope>;
1414
1415 #[inline]
1416 fn scope(&self) -> IpAddr<(), Ipv6Scope> {
1417 match self {
1418 IpAddr::V4(_) => IpAddr::V4(()),
1419 IpAddr::V6(addr) => IpAddr::V6(addr.scope()),
1420 }
1421 }
1422}
1423
1424macro_rules! impl_from_witness {
1447 ($witness:ident, $witness_trait:ident) => {
1448 impl From<IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>> for $witness<IpAddr> {
1449 fn from(addr: IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>) -> $witness<IpAddr> {
1450 unsafe {
1451 Witness::new_unchecked(match addr {
1452 IpAddr::V4(addr) => IpAddr::V4(addr.get()),
1453 IpAddr::V6(addr) => IpAddr::V6(addr.get()),
1454 })
1455 }
1456 }
1457 }
1458 impl From<$witness<IpAddr>> for IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1459 fn from(addr: $witness<IpAddr>) -> IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1460 unsafe {
1461 match addr.get() {
1462 IpAddr::V4(addr) => IpAddr::V4(Witness::new_unchecked(addr)),
1463 IpAddr::V6(addr) => IpAddr::V6(Witness::new_unchecked(addr)),
1464 }
1465 }
1466 }
1467 }
1468 impl<A: IpAddress> From<$witness<A>> for $witness<IpAddr> {
1469 fn from(addr: $witness<A>) -> $witness<IpAddr> {
1470 unsafe { Witness::new_unchecked(addr.to_ip_addr()) }
1471 }
1472 }
1473 impl<A: IpAddress> From<$witness<A>> for IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1474 fn from(addr: $witness<A>) -> IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1475 let addr: $witness<IpAddr> = addr.into();
1476 addr.into()
1477 }
1478 }
1479 impl<A: Into<Ipv4Addr> + $witness_trait + Copy> From<$witness<A>> for Ipv4Addr {
1481 fn from(addr: $witness<A>) -> Ipv4Addr {
1482 let addr: A = addr.get();
1483 addr.into()
1484 }
1485 }
1486 impl<A: Into<Ipv6Addr> + $witness_trait + Copy> From<$witness<A>> for Ipv6Addr {
1487 fn from(addr: $witness<A>) -> Ipv6Addr {
1488 let addr: A = addr.get();
1489 addr.into()
1490 }
1491 }
1492 impl TryFrom<Ipv4Addr> for $witness<Ipv4Addr> {
1494 type Error = ();
1495 fn try_from(addr: Ipv4Addr) -> Result<$witness<Ipv4Addr>, ()> {
1496 Witness::new(addr).ok_or(())
1497 }
1498 }
1499 impl TryFrom<Ipv6Addr> for $witness<Ipv6Addr> {
1500 type Error = ();
1501 fn try_from(addr: Ipv6Addr) -> Result<$witness<Ipv6Addr>, ()> {
1502 Witness::new(addr).ok_or(())
1503 }
1504 }
1505 };
1506 ($witness:ident, $witness_trait:ident, $ipaddr:ident, $new_unchecked:expr) => {
1507 impl From<$witness<$ipaddr>> for $witness<IpAddr> {
1508 fn from(addr: $witness<$ipaddr>) -> $witness<IpAddr> {
1509 let addr: $ipaddr = addr.get();
1510 let addr: IpAddr = addr.into();
1511 #[allow(unused_unsafe)] unsafe {
1513 $new_unchecked(addr)
1514 }
1515 }
1516 }
1517 impl<A: Into<$ipaddr> + $witness_trait + Copy> From<$witness<A>> for $ipaddr {
1518 fn from(addr: $witness<A>) -> $ipaddr {
1519 let addr: A = addr.get();
1520 addr.into()
1521 }
1522 }
1523 impl TryFrom<$ipaddr> for $witness<$ipaddr> {
1524 type Error = ();
1525 fn try_from(addr: $ipaddr) -> Result<$witness<$ipaddr>, ()> {
1526 Witness::new(addr).ok_or(())
1527 }
1528 }
1529 };
1530}
1531
1532impl_from_witness!(SpecifiedAddr, SpecifiedAddress);
1533impl_from_witness!(MulticastAddr, MulticastAddress);
1534impl_from_witness!(LinkLocalAddr, LinkLocalAddress);
1535impl_from_witness!(NonMappedAddr, MappedAddress);
1536impl_from_witness!(UnicastAddr, UnicastAddress, Ipv6Addr, UnicastAddr::new_unchecked);
1539
1540#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1550pub enum Ipv4AddressClass {
1551 A,
1553 B,
1555 C,
1557 D,
1561 E,
1565}
1566
1567impl Ipv4AddressClass {
1568 pub const fn default_prefix_len(self) -> Option<u8> {
1571 match self {
1609 Ipv4AddressClass::A => Some(8),
1610 Ipv4AddressClass::B => Some(16),
1611 Ipv4AddressClass::C => Some(24),
1612 Ipv4AddressClass::D => None,
1613 Ipv4AddressClass::E => None,
1614 }
1615 }
1616}
1617
1618#[derive(
1641 Copy,
1642 Clone,
1643 Default,
1644 PartialEq,
1645 Eq,
1646 PartialOrd,
1647 Ord,
1648 Hash,
1649 KnownLayout,
1650 FromBytes,
1651 IntoBytes,
1652 Immutable,
1653 Unaligned,
1654)]
1655#[repr(transparent)]
1656pub struct Ipv4Addr([u8; 4]);
1657
1658impl Ipv4Addr {
1659 #[inline]
1661 pub const fn new(bytes: [u8; 4]) -> Self {
1662 Ipv4Addr(bytes)
1663 }
1664
1665 #[inline]
1667 pub const fn ipv4_bytes(self) -> [u8; 4] {
1668 self.0
1669 }
1670
1671 #[inline]
1676 pub fn is_limited_broadcast(self) -> bool {
1677 self == Ipv4::LIMITED_BROADCAST_ADDRESS.get()
1678 }
1679
1680 #[inline]
1685 pub fn is_class_e(self) -> bool {
1686 Ipv4::CLASS_E_SUBNET.contains(&self)
1687 }
1688
1689 #[inline]
1717 pub fn to_ipv6_compatible(self) -> Ipv6Addr {
1718 let Self([a, b, c, d]) = self;
1719 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
1720 }
1721
1722 #[inline]
1740 pub fn to_ipv6_mapped(self) -> SpecifiedAddr<Ipv6Addr> {
1741 let Self([a, b, c, d]) = self;
1742 SpecifiedAddr::new(Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d]))
1743 .unwrap()
1744 }
1745
1746 pub fn class(&self) -> Ipv4AddressClass {
1749 for (subnet, class) in [
1750 (Ipv4::CLASS_A_SUBNET, Ipv4AddressClass::A),
1751 (Ipv4::CLASS_B_SUBNET, Ipv4AddressClass::B),
1752 (Ipv4::CLASS_C_SUBNET, Ipv4AddressClass::C),
1753 (Ipv4::CLASS_D_SUBNET, Ipv4AddressClass::D),
1754 (Ipv4::CLASS_E_SUBNET, Ipv4AddressClass::E),
1755 ] {
1756 if subnet.contains(self) {
1757 return class;
1758 }
1759 }
1760
1761 unreachable!("{} should fit into a class", self)
1762 }
1763}
1764
1765impl sealed::Sealed for Ipv4Addr {}
1766
1767impl IpAddress for Ipv4Addr {
1768 const BYTES: u8 = 4;
1769
1770 type Version = Ipv4;
1771
1772 #[inline]
1773 fn mask(&self, bits: u8) -> Self {
1774 assert!(bits <= 32);
1775 let mask = u32::MAX.checked_shl((32 - bits).into()).unwrap_or(0);
1779 Ipv4Addr((u32::from_be_bytes(self.0) & mask).to_be_bytes())
1780 }
1781
1782 #[inline]
1783 fn bytes(&self) -> &[u8] {
1784 &self.0
1785 }
1786
1787 #[inline]
1788 fn to_ip_addr(&self) -> IpAddr {
1789 IpAddr::V4(*self)
1790 }
1791
1792 #[inline]
1793 fn common_prefix_len(&self, other: &Ipv4Addr) -> u8 {
1794 let me = u32::from_be_bytes(self.0);
1795 let other = u32::from_be_bytes(other.0);
1796 let same_bits = me ^ other;
1799 same_bits.leading_zeros() as u8
1800 }
1801
1802 #[inline]
1803 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool {
1804 !self.is_multicast()
1805 && !self.is_limited_broadcast()
1806 && (subnet.prefix() == 32
1810 || subnet.prefix() == 31
1811 || (*self != subnet.broadcast() && *self != subnet.network()))
1812 && self.is_specified()
1813 && !self.is_class_e()
1814 && subnet.contains(self)
1815 }
1816
1817 fn subnet_into_either(subnet: Subnet<Ipv4Addr>) -> SubnetEither {
1818 SubnetEither::V4(subnet)
1819 }
1820
1821 #[inline]
1822 fn array_into_ip_addr<const N: usize>(
1823 addrs: [Self; N],
1824 ) -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
1825 IpAddr::V4(addrs)
1826 }
1827}
1828
1829impl From<[u8; 4]> for Ipv4Addr {
1830 #[inline]
1831 fn from(bytes: [u8; 4]) -> Ipv4Addr {
1832 Ipv4Addr(bytes)
1833 }
1834}
1835
1836#[cfg(feature = "std")]
1837impl From<net::Ipv4Addr> for Ipv4Addr {
1838 #[inline]
1839 fn from(ip: net::Ipv4Addr) -> Ipv4Addr {
1840 Ipv4Addr::new(ip.octets())
1841 }
1842}
1843
1844#[cfg(feature = "std")]
1845impl From<Ipv4Addr> for net::Ipv4Addr {
1846 #[inline]
1847 fn from(ip: Ipv4Addr) -> net::Ipv4Addr {
1848 net::Ipv4Addr::from(ip.0)
1849 }
1850}
1851
1852impl Display for Ipv4Addr {
1853 #[inline]
1854 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1855 write!(f, "{}.{}.{}.{}", self.0[0], self.0[1], self.0[2], self.0[3])
1856 }
1857}
1858
1859impl Debug for Ipv4Addr {
1860 #[inline]
1861 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1862 Display::fmt(self, f)
1863 }
1864}
1865
1866#[derive(
1901 Copy,
1902 Clone,
1903 Default,
1904 PartialEq,
1905 Eq,
1906 PartialOrd,
1907 Ord,
1908 Hash,
1909 KnownLayout,
1910 FromBytes,
1911 IntoBytes,
1912 Immutable,
1913 Unaligned,
1914)]
1915#[repr(transparent)]
1916pub struct Ipv6Addr([u8; 16]);
1917
1918impl Ipv6Addr {
1919 #[inline]
1921 pub const fn new(segments: [u16; 8]) -> Ipv6Addr {
1922 #![allow(clippy::many_single_char_names)]
1923 let [a, b, c, d, e, f, g, h] = segments;
1924 let [aa, ab] = a.to_be_bytes();
1925 let [ba, bb] = b.to_be_bytes();
1926 let [ca, cb] = c.to_be_bytes();
1927 let [da, db] = d.to_be_bytes();
1928 let [ea, eb] = e.to_be_bytes();
1929 let [fa, fb] = f.to_be_bytes();
1930 let [ga, gb] = g.to_be_bytes();
1931 let [ha, hb] = h.to_be_bytes();
1932 Ipv6Addr([aa, ab, ba, bb, ca, cb, da, db, ea, eb, fa, fb, ga, gb, ha, hb])
1933 }
1934
1935 #[inline]
1937 pub const fn from_bytes(bytes: [u8; 16]) -> Ipv6Addr {
1938 Ipv6Addr(bytes)
1939 }
1940
1941 #[inline]
1943 pub const fn ipv6_bytes(&self) -> [u8; 16] {
1944 self.0
1945 }
1946
1947 #[inline]
1949 pub fn segments(&self) -> [u16; 8] {
1950 #![allow(clippy::many_single_char_names)]
1951 let [a, b, c, d, e, f, g, h]: [zerocopy::network_endian::U16; 8] =
1952 zerocopy::transmute!(self.ipv6_bytes());
1953 [a.into(), b.into(), c.into(), d.into(), e.into(), f.into(), g.into(), h.into()]
1954 }
1955
1956 #[inline]
1961 pub const fn to_solicited_node_address(&self) -> MulticastAddr<Ipv6Addr> {
1962 unsafe {
1970 MulticastAddr::new_unchecked(Ipv6Addr::from_bytes([
1971 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xff, self.0[13], self.0[14],
1972 self.0[15],
1973 ]))
1974 }
1975 }
1976
1977 #[inline]
1984 pub fn is_valid_unicast(&self) -> bool {
1985 !(self.is_loopback() || !self.is_specified() || self.is_multicast())
1986 }
1987
1988 #[inline]
1995 pub fn is_site_local(&self) -> bool {
1996 Ipv6::SITE_LOCAL_UNICAST_SUBNET.contains(self)
1997 }
1998
1999 #[inline]
2004 pub fn is_unicast_link_local(&self) -> bool {
2005 self.is_unicast_in_subnet(&Ipv6::LINK_LOCAL_UNICAST_SUBNET)
2006 }
2007
2008 pub fn to_ipv4_compatible(&self) -> Option<Ipv4Addr> {
2038 if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] = self.0 {
2039 Some(Ipv4Addr::new([a, b, c, d]))
2040 } else {
2041 None
2042 }
2043 }
2044
2045 pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
2065 if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] = self.0 {
2066 Some(Ipv4Addr::new([a, b, c, d]))
2067 } else {
2068 None
2069 }
2070 }
2071}
2072
2073impl sealed::Sealed for Ipv6Addr {}
2074
2075impl From<Ipv4Addr> for Ipv6Addr {
2078 fn from(addr: Ipv4Addr) -> Ipv6Addr {
2079 *addr.to_ipv6_mapped()
2080 }
2081}
2082
2083impl IpAddress for Ipv6Addr {
2084 const BYTES: u8 = 16;
2085
2086 type Version = Ipv6;
2087
2088 #[inline]
2089 fn mask(&self, bits: u8) -> Ipv6Addr {
2090 assert!(bits <= 128);
2091 let mask = u128::MAX.checked_shl((128 - bits).into()).unwrap_or(0);
2095 Ipv6Addr((u128::from_be_bytes(self.0) & mask).to_be_bytes())
2096 }
2097
2098 #[inline]
2099 fn bytes(&self) -> &[u8] {
2100 &self.0
2101 }
2102
2103 #[inline]
2104 fn to_ip_addr(&self) -> IpAddr {
2105 IpAddr::V6(*self)
2106 }
2107
2108 #[inline]
2109 fn common_prefix_len(&self, other: &Ipv6Addr) -> u8 {
2110 let me = u128::from_be_bytes(self.0);
2111 let other = u128::from_be_bytes(other.0);
2112 let same_bits = me ^ other;
2115 same_bits.leading_zeros() as u8
2116 }
2117
2118 #[inline]
2119 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool {
2120 !self.is_multicast() && self.is_specified() && subnet.contains(self)
2121 }
2122
2123 fn subnet_into_either(subnet: Subnet<Ipv6Addr>) -> SubnetEither {
2124 SubnetEither::V6(subnet)
2125 }
2126
2127 #[inline]
2128 fn array_into_ip_addr<const N: usize>(
2129 addrs: [Self; N],
2130 ) -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
2131 IpAddr::V6(addrs)
2132 }
2133}
2134
2135impl UnicastAddress for Ipv6Addr {
2136 #[inline]
2141 fn is_unicast(&self) -> bool {
2142 !self.is_multicast() && self.is_specified()
2143 }
2144}
2145
2146impl From<[u8; 16]> for Ipv6Addr {
2147 #[inline]
2148 fn from(bytes: [u8; 16]) -> Ipv6Addr {
2149 Ipv6Addr::from_bytes(bytes)
2150 }
2151}
2152
2153#[cfg(feature = "std")]
2154impl From<net::Ipv6Addr> for Ipv6Addr {
2155 #[inline]
2156 fn from(addr: net::Ipv6Addr) -> Ipv6Addr {
2157 Ipv6Addr::from_bytes(addr.octets())
2158 }
2159}
2160
2161#[cfg(feature = "std")]
2162impl From<Ipv6Addr> for net::Ipv6Addr {
2163 #[inline]
2164 fn from(addr: Ipv6Addr) -> net::Ipv6Addr {
2165 net::Ipv6Addr::from(addr.ipv6_bytes())
2166 }
2167}
2168
2169impl Display for Ipv6Addr {
2170 #[inline]
2179 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2180 fn fmt_inner<W: fmt::Write>(addr: &Ipv6Addr, w: &mut W) -> Result<(), fmt::Error> {
2185 if !addr.is_specified() {
2189 write!(w, "::")
2190 } else if addr.is_loopback() {
2191 write!(w, "::1")
2192 } else if let Some(v4) = addr.to_ipv4_mapped() {
2193 write!(w, "::ffff:{}", v4)
2194 } else {
2195 let segments = addr.segments();
2196
2197 let longest_zero_span = {
2198 let mut longest_zero_span = 0..0;
2199 let mut current_zero_span = 0..0;
2200 for (i, seg) in segments.iter().enumerate() {
2201 if *seg == 0 {
2202 current_zero_span.end = i + 1;
2203 if current_zero_span.len() > longest_zero_span.len() {
2204 longest_zero_span = current_zero_span.clone();
2205 }
2206 } else {
2207 let next_idx = i + 1;
2208 current_zero_span = next_idx..next_idx;
2209 }
2210 }
2211 longest_zero_span
2212 };
2213
2214 let write_slice = |w: &mut W, slice: &[u16]| {
2215 if let [head, tail @ ..] = slice {
2216 write!(w, "{:x}", head)?;
2217 for seg in tail {
2218 write!(w, ":{:x}", seg)?;
2219 }
2220 }
2221 Ok(())
2222 };
2223
2224 if longest_zero_span.len() > 1 {
2241 write_slice(w, &segments[..longest_zero_span.start])?;
2242 w.write_str("::")?;
2243 write_slice(w, &segments[longest_zero_span.end..])
2244 } else {
2245 write_slice(w, &segments)
2246 }
2247 }
2248 }
2249
2250 if f.precision().is_none() && f.width().is_none() {
2251 fmt_inner(self, f)
2254 } else {
2255 struct ByteSlice<'a>(&'a mut [u8]);
2262
2263 impl<'a> fmt::Write for ByteSlice<'a> {
2264 fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
2265 let from = s.as_bytes();
2266
2267 if from.len() > self.0.len() {
2268 return Err(fmt::Error);
2269 }
2270
2271 let to = mem::replace(&mut self.0, &mut [][..]);
2277 let (to, remaining) = to.split_at_mut(from.len());
2278 to.copy_from_slice(from);
2279
2280 self.0 = remaining;
2281 Ok(())
2282 }
2283 }
2284
2285 const MAX_DISPLAY_LEN: usize = (4 * 8) + 7;
2289 let mut scratch = [0u8; MAX_DISPLAY_LEN];
2290 let mut scratch_slice = ByteSlice(&mut scratch[..]);
2291 fmt_inner(self, &mut scratch_slice)
2298 .expect("<Ipv6Addr as Display>::fmt: fmt_inner should have succeeded because the scratch buffer was long enough");
2299 let unwritten = scratch_slice.0.len();
2300 let len = MAX_DISPLAY_LEN - unwritten;
2301 let str = core::str::from_utf8(&scratch[..len])
2303 .expect("<Ipv6Addr as Display>::fmt: scratch buffer should contain valid UTF-8");
2304 f.pad(str)
2305 }
2306 }
2307}
2308
2309impl Debug for Ipv6Addr {
2310 #[inline]
2311 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2312 Display::fmt(self, f)
2313 }
2314}
2315
2316#[allow(missing_docs)]
2323#[derive(Copy, Clone, Eq, PartialEq)]
2324pub enum Ipv6SourceAddr {
2325 Unicast(NonMappedAddr<UnicastAddr<Ipv6Addr>>),
2326 Unspecified,
2327}
2328
2329impl crate::sealed::Sealed for Ipv6SourceAddr {}
2330
2331impl Ipv6SourceAddr {
2332 #[inline]
2337 pub fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2338 if let Some(addr) = UnicastAddr::new(addr) {
2339 NonMappedAddr::new(addr).map(Ipv6SourceAddr::Unicast)
2340 } else if !addr.is_specified() {
2341 Some(Ipv6SourceAddr::Unspecified)
2342 } else {
2343 None
2344 }
2345 }
2346}
2347
2348impl Witness<Ipv6Addr> for Ipv6SourceAddr {
2349 #[inline]
2350 fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2351 Ipv6SourceAddr::new(addr)
2352 }
2353
2354 #[inline]
2355 unsafe fn new_unchecked(addr: Ipv6Addr) -> Ipv6SourceAddr {
2356 Ipv6SourceAddr::new(addr).unwrap()
2357 }
2358
2359 #[inline]
2360 fn into_addr(self) -> Ipv6Addr {
2361 match self {
2362 Ipv6SourceAddr::Unicast(addr) => **addr,
2363 Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2364 }
2365 }
2366}
2367
2368impl SpecifiedAddress for Ipv6SourceAddr {
2369 fn is_specified(&self) -> bool {
2370 self != &Ipv6SourceAddr::Unspecified
2371 }
2372}
2373
2374impl UnicastAddress for Ipv6SourceAddr {
2375 fn is_unicast(&self) -> bool {
2376 matches!(self, Ipv6SourceAddr::Unicast(_))
2377 }
2378}
2379
2380impl LinkLocalAddress for Ipv6SourceAddr {
2381 fn is_link_local(&self) -> bool {
2382 let addr: Ipv6Addr = self.into();
2383 addr.is_link_local()
2384 }
2385}
2386
2387impl MappedAddress for Ipv6SourceAddr {
2388 fn is_non_mapped(&self) -> bool {
2389 let addr: Ipv6Addr = self.into();
2390 addr.is_non_mapped()
2391 }
2392}
2393
2394impl From<Ipv6SourceAddr> for Ipv6Addr {
2395 fn from(addr: Ipv6SourceAddr) -> Ipv6Addr {
2396 addr.get()
2397 }
2398}
2399
2400impl From<&'_ Ipv6SourceAddr> for Ipv6Addr {
2401 fn from(addr: &Ipv6SourceAddr) -> Ipv6Addr {
2402 match addr {
2403 Ipv6SourceAddr::Unicast(addr) => addr.get(),
2404 Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2405 }
2406 }
2407}
2408
2409impl TryFrom<Ipv6Addr> for Ipv6SourceAddr {
2410 type Error = ();
2411 fn try_from(addr: Ipv6Addr) -> Result<Ipv6SourceAddr, ()> {
2412 Ipv6SourceAddr::new(addr).ok_or(())
2413 }
2414}
2415
2416impl AsRef<Ipv6Addr> for Ipv6SourceAddr {
2417 fn as_ref(&self) -> &Ipv6Addr {
2418 match self {
2419 Ipv6SourceAddr::Unicast(addr) => addr,
2420 Ipv6SourceAddr::Unspecified => &Ipv6::UNSPECIFIED_ADDRESS,
2421 }
2422 }
2423}
2424
2425impl Deref for Ipv6SourceAddr {
2426 type Target = Ipv6Addr;
2427
2428 fn deref(&self) -> &Ipv6Addr {
2429 self.as_ref()
2430 }
2431}
2432
2433impl Display for Ipv6SourceAddr {
2434 #[inline]
2435 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2436 match self {
2437 Ipv6SourceAddr::Unicast(addr) => write!(f, "{}", addr),
2438 Ipv6SourceAddr::Unspecified => write!(f, "::"),
2439 }
2440 }
2441}
2442
2443impl Debug for Ipv6SourceAddr {
2444 #[inline]
2445 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2446 Display::fmt(self, f)
2447 }
2448}
2449
2450#[allow(missing_docs)]
2458#[derive(Copy, Clone, Eq, PartialEq)]
2459pub enum UnicastOrMulticastIpv6Addr {
2460 Unicast(UnicastAddr<Ipv6Addr>),
2461 Multicast(MulticastAddr<Ipv6Addr>),
2462}
2463
2464impl UnicastOrMulticastIpv6Addr {
2465 pub fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2469 SpecifiedAddr::new(addr).map(UnicastOrMulticastIpv6Addr::from_specified)
2470 }
2471
2472 pub fn from_specified(addr: SpecifiedAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2474 if addr.is_unicast() {
2475 UnicastOrMulticastIpv6Addr::Unicast(UnicastAddr(addr.get()))
2476 } else {
2477 UnicastOrMulticastIpv6Addr::Multicast(MulticastAddr(addr.get()))
2478 }
2479 }
2480}
2481
2482impl crate::sealed::Sealed for UnicastOrMulticastIpv6Addr {}
2483
2484impl Witness<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2485 #[inline]
2486 fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2487 UnicastOrMulticastIpv6Addr::new(addr)
2488 }
2489
2490 #[inline]
2491 unsafe fn new_unchecked(addr: Ipv6Addr) -> UnicastOrMulticastIpv6Addr {
2492 UnicastOrMulticastIpv6Addr::new(addr).unwrap()
2493 }
2494
2495 #[inline]
2496 fn into_addr(self) -> Ipv6Addr {
2497 match self {
2498 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.get(),
2499 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.get(),
2500 }
2501 }
2502}
2503
2504impl UnicastAddress for UnicastOrMulticastIpv6Addr {
2505 fn is_unicast(&self) -> bool {
2506 matches!(self, UnicastOrMulticastIpv6Addr::Unicast(_))
2507 }
2508}
2509
2510impl MulticastAddress for UnicastOrMulticastIpv6Addr {
2511 fn is_multicast(&self) -> bool {
2512 matches!(self, UnicastOrMulticastIpv6Addr::Multicast(_))
2513 }
2514}
2515
2516impl LinkLocalAddress for UnicastOrMulticastIpv6Addr {
2517 fn is_link_local(&self) -> bool {
2518 match self {
2519 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_link_local(),
2520 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_link_local(),
2521 }
2522 }
2523}
2524
2525impl MappedAddress for UnicastOrMulticastIpv6Addr {
2526 fn is_non_mapped(&self) -> bool {
2527 match self {
2528 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_non_mapped(),
2529 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_non_mapped(),
2530 }
2531 }
2532}
2533
2534impl From<UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2535 fn from(addr: UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2536 addr.get()
2537 }
2538}
2539
2540impl From<&'_ UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2541 fn from(addr: &UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2542 addr.get()
2543 }
2544}
2545
2546impl From<UnicastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2547 fn from(addr: UnicastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2548 UnicastOrMulticastIpv6Addr::Unicast(addr)
2549 }
2550}
2551
2552impl From<MulticastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2553 fn from(addr: MulticastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2554 UnicastOrMulticastIpv6Addr::Multicast(addr)
2555 }
2556}
2557
2558impl TryFrom<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2559 type Error = ();
2560 fn try_from(addr: Ipv6Addr) -> Result<UnicastOrMulticastIpv6Addr, ()> {
2561 UnicastOrMulticastIpv6Addr::new(addr).ok_or(())
2562 }
2563}
2564
2565impl AsRef<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2566 fn as_ref(&self) -> &Ipv6Addr {
2567 match self {
2568 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr,
2569 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr,
2570 }
2571 }
2572}
2573
2574impl Deref for UnicastOrMulticastIpv6Addr {
2575 type Target = Ipv6Addr;
2576
2577 fn deref(&self) -> &Ipv6Addr {
2578 self.as_ref()
2579 }
2580}
2581
2582impl Display for UnicastOrMulticastIpv6Addr {
2583 #[inline]
2584 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2585 match self {
2586 UnicastOrMulticastIpv6Addr::Unicast(addr) => write!(f, "{}", addr),
2587 UnicastOrMulticastIpv6Addr::Multicast(addr) => write!(f, "{}", addr),
2588 }
2589 }
2590}
2591
2592impl Debug for UnicastOrMulticastIpv6Addr {
2593 #[inline]
2594 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2595 Display::fmt(self, f)
2596 }
2597}
2598
2599#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2601pub enum SubnetError {
2602 PrefixTooLong,
2605 HostBitsSet,
2608}
2609
2610#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2613pub struct PrefixTooLongError;
2614
2615#[derive(Copy, Clone, Eq, PartialEq, Hash)]
2619pub struct Subnet<A> {
2620 network: A,
2622 prefix: u8,
2623}
2624
2625impl<A: core::cmp::Ord> core::cmp::PartialOrd for Subnet<A> {
2626 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
2627 Some(self.cmp(other))
2628 }
2629}
2630
2631impl<A: core::cmp::Ord> core::cmp::Ord for Subnet<A> {
2633 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
2634 let Self { network, prefix } = self;
2635 let Self { network: other_network, prefix: other_prefix } = other;
2636 match prefix.cmp(other_prefix) {
2637 core::cmp::Ordering::Equal => network.cmp(other_network),
2638 ord => ord,
2639 }
2640 }
2641}
2642
2643impl<A> Subnet<A> {
2644 #[inline]
2654 pub const unsafe fn new_unchecked(network: A, prefix: u8) -> Subnet<A> {
2655 Subnet { network, prefix }
2656 }
2657}
2658
2659impl<A: IpAddress> Subnet<A> {
2660 #[inline]
2667 pub fn new(network: A, prefix: u8) -> Result<Subnet<A>, SubnetError> {
2668 if prefix > A::BYTES * 8 {
2669 return Err(SubnetError::PrefixTooLong);
2670 }
2671 if network != network.mask(prefix) {
2674 return Err(SubnetError::HostBitsSet);
2675 }
2676 Ok(Subnet { network, prefix })
2677 }
2678
2679 #[inline]
2685 pub fn from_host(host: A, prefix: u8) -> Result<Subnet<A>, PrefixTooLongError> {
2686 if prefix > A::BYTES * 8 {
2687 return Err(PrefixTooLongError);
2688 }
2689 let network = host.mask(prefix);
2690 Ok(Subnet { network, prefix })
2691 }
2692
2693 #[inline]
2697 pub fn network(&self) -> A {
2698 self.network
2699 }
2700
2701 #[inline]
2703 pub fn prefix(&self) -> u8 {
2704 self.prefix
2705 }
2706
2707 #[inline]
2713 pub fn contains(&self, addr: &A) -> bool {
2714 self.network == addr.mask(self.prefix)
2715 }
2716}
2717
2718impl Subnet<Ipv4Addr> {
2719 #[inline]
2727 pub fn broadcast(self) -> Ipv4Addr {
2728 if self.prefix == 32 {
2729 self.network
2731 } else {
2732 let mask = <u32>::max_value() >> self.prefix;
2733 Ipv4Addr::new((u32::from_be_bytes(self.network.0) | mask).to_be_bytes())
2734 }
2735 }
2736}
2737
2738impl<A: IpAddress> Display for Subnet<A> {
2739 #[inline]
2740 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2741 write!(f, "{}/{}", self.network, self.prefix)
2742 }
2743}
2744
2745impl<A: IpAddress> Debug for Subnet<A> {
2746 #[inline]
2747 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2748 write!(f, "{}/{}", self.network, self.prefix)
2749 }
2750}
2751
2752impl<A, I: Ip> GenericOverIp<I> for Subnet<A> {
2753 type Type = Subnet<I::Addr>;
2754}
2755
2756#[allow(missing_docs)]
2762#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2763pub enum SubnetEither {
2764 V4(Subnet<Ipv4Addr>),
2765 V6(Subnet<Ipv6Addr>),
2766}
2767
2768impl SubnetEither {
2769 #[inline]
2776 pub fn new(network: IpAddr, prefix: u8) -> Result<SubnetEither, SubnetError> {
2777 Ok(match network {
2778 IpAddr::V4(network) => SubnetEither::V4(Subnet::new(network, prefix)?),
2779 IpAddr::V6(network) => SubnetEither::V6(Subnet::new(network, prefix)?),
2780 })
2781 }
2782
2783 #[inline]
2789 pub fn from_host(host: IpAddr, prefix: u8) -> Result<SubnetEither, PrefixTooLongError> {
2790 Ok(match host {
2791 IpAddr::V4(host) => SubnetEither::V4(Subnet::from_host(host, prefix)?),
2792 IpAddr::V6(host) => SubnetEither::V6(Subnet::from_host(host, prefix)?),
2793 })
2794 }
2795
2796 #[inline]
2798 pub fn net_prefix(&self) -> (IpAddr, u8) {
2799 match self {
2800 SubnetEither::V4(v4) => (v4.network.into(), v4.prefix),
2801 SubnetEither::V6(v6) => (v6.network.into(), v6.prefix),
2802 }
2803 }
2804}
2805
2806impl<A: IpAddress> From<Subnet<A>> for SubnetEither {
2807 fn from(subnet: Subnet<A>) -> SubnetEither {
2808 A::subnet_into_either(subnet)
2809 }
2810}
2811
2812#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2814pub enum AddrSubnetError {
2815 PrefixTooLong,
2818 NotUnicastInSubnet,
2821 InvalidWitness,
2823}
2824
2825#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2836pub struct AddrSubnet<S: IpAddress, A: Witness<S> + Copy = SpecifiedAddr<S>> {
2837 addr: A,
2841 subnet: Subnet<S>,
2842}
2843
2844impl<S: IpAddress, A: Witness<S> + Copy> AddrSubnet<S, A> {
2845 #[inline]
2853 pub fn new(addr: S, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2854 AddrSubnet::from_witness(A::new(addr).ok_or(AddrSubnetError::InvalidWitness)?, prefix)
2855 }
2856
2857 #[inline]
2868 pub unsafe fn new_unchecked(addr: S, prefix: u8) -> Self {
2869 let (subnet, addr) =
2870 unsafe { (Subnet::new_unchecked(addr.mask(prefix), prefix), A::new_unchecked(addr)) };
2871 AddrSubnet { addr, subnet }
2872 }
2873
2874 pub fn from_witness(addr: A, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2883 if prefix > S::BYTES * 8 {
2884 return Err(AddrSubnetError::PrefixTooLong);
2885 }
2886 let subnet = Subnet { network: addr.as_ref().mask(prefix), prefix };
2887 if !addr.as_ref().is_unicast_in_subnet(&subnet) {
2888 return Err(AddrSubnetError::NotUnicastInSubnet);
2889 }
2890 Ok(AddrSubnet { addr, subnet })
2891 }
2892
2893 #[inline]
2895 pub fn subnet(&self) -> Subnet<S> {
2896 self.subnet
2897 }
2898
2899 #[inline]
2901 pub fn addr(&self) -> A {
2902 self.addr
2903 }
2904
2905 #[inline]
2907 pub fn addr_subnet(self) -> (A, Subnet<S>) {
2908 (self.addr, self.subnet)
2909 }
2910
2911 #[inline]
2913 pub fn to_witness<B: Witness<S> + Copy>(&self) -> AddrSubnet<S, B>
2914 where
2915 A: Into<B>,
2916 {
2917 AddrSubnet { addr: self.addr.into(), subnet: self.subnet }
2918 }
2919
2920 #[inline]
2922 pub fn add_witness<B: Witness<A> + Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
2923 let addr = B::new(self.addr)?;
2924 Some(AddrSubnet { addr, subnet: self.subnet })
2925 }
2926
2927 #[inline]
2929 pub fn replace_witness<B: Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
2930 let addr = B::new(self.addr.get())?;
2931 Some(AddrSubnet { addr, subnet: self.subnet })
2932 }
2933}
2934
2935impl<S: IpAddress, A: Witness<S> + Copy + Display> Display for AddrSubnet<S, A> {
2936 #[inline]
2937 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2938 write!(f, "{}/{}", self.addr, self.subnet.prefix)
2939 }
2940}
2941
2942impl<A: Witness<Ipv6Addr> + Copy> AddrSubnet<Ipv6Addr, A> {
2943 pub fn ipv6_unicast_addr(&self) -> UnicastAddr<Ipv6Addr> {
2949 unsafe { UnicastAddr::new_unchecked(self.addr.get()) }
2950 }
2951
2952 pub fn to_unicast(&self) -> AddrSubnet<Ipv6Addr, UnicastAddr<Ipv6Addr>> {
2958 let AddrSubnet { addr, subnet } = *self;
2959 let addr = unsafe { UnicastAddr::new_unchecked(addr.get()) };
2960 AddrSubnet { addr, subnet }
2961 }
2962}
2963
2964#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, GenericOverIp)]
2966#[generic_over_ip(I, Ip)]
2967pub struct PrefixLength<I: Ip> {
2968 inner: u8,
2970 _ip: IpVersionMarker<I>,
2971}
2972
2973impl<I: Ip> PrefixLength<I> {
2974 pub const fn get(self) -> u8 {
2979 let Self { inner, _ip } = self;
2980 inner
2981 }
2982
2983 pub fn get_mask(self) -> I::Addr {
2985 I::map_ip(
2986 self,
2987 |prefix_len| Ipv4::LIMITED_BROADCAST_ADDRESS.mask(prefix_len.get()),
2988 |prefix_len| Ipv6Addr([u8::MAX; 16]).mask(prefix_len.get()),
2989 )
2990 }
2991
2992 pub const unsafe fn new_unchecked(prefix_length: u8) -> Self {
2999 Self { inner: prefix_length, _ip: I::VERSION_MARKER }
3000 }
3001
3002 pub const fn new(prefix_length: u8) -> Result<Self, PrefixTooLongError> {
3007 if prefix_length > I::Addr::BYTES * 8 {
3008 return Err(PrefixTooLongError);
3009 }
3010 Ok(Self { inner: prefix_length, _ip: I::VERSION_MARKER })
3011 }
3012
3013 pub fn try_from_subnet_mask(subnet_mask: I::Addr) -> Result<Self, NotSubnetMaskError> {
3018 let IpInvariant((count_ones, leading_ones)) = I::map_ip(
3019 subnet_mask,
3020 |subnet_mask| {
3021 let number = u32::from_be_bytes(subnet_mask.ipv4_bytes());
3022 IpInvariant((number.count_ones(), number.leading_ones()))
3023 },
3024 |subnet_mask| {
3025 let number = u128::from_be_bytes(subnet_mask.ipv6_bytes());
3026 IpInvariant((number.count_ones(), number.leading_ones()))
3027 },
3028 );
3029
3030 if leading_ones != count_ones {
3031 return Err(NotSubnetMaskError);
3032 }
3033
3034 Ok(Self {
3035 inner: u8::try_from(leading_ones)
3036 .expect("the number of bits in an IP address fits in u8"),
3037 _ip: IpVersionMarker::default(),
3038 })
3039 }
3040}
3041
3042impl<I: Ip> From<PrefixLength<I>> for u8 {
3043 fn from(value: PrefixLength<I>) -> Self {
3044 value.get()
3045 }
3046}
3047
3048#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3051pub struct NotSubnetMaskError;
3052
3053pub trait IpAddressWitness<A: IpAddress>: Witness<A> {
3066 type IpAddrWitness: IpAddrWitness + From<Self>;
3071}
3072
3073macro_rules! impl_ip_address_witness {
3074 ($witness:ident) => {
3075 impl<A: IpAddress> IpAddressWitness<A> for $witness<A> {
3076 type IpAddrWitness = $witness<IpAddr>;
3077 }
3078 };
3079}
3080
3081impl_ip_address_witness!(SpecifiedAddr);
3082impl_ip_address_witness!(MulticastAddr);
3083impl_ip_address_witness!(LinkLocalAddr);
3084
3085pub trait IpAddrWitness: Witness<IpAddr> + Into<IpAddr<Self::V4, Self::V6>> + Copy {
3099 type V4: Witness<Ipv4Addr> + Into<Self> + Copy;
3104
3105 type V6: Witness<Ipv6Addr> + Into<Self> + Copy;
3110
3111 fn from_v4(addr: Self::V4) -> Self {
3116 addr.into()
3117 }
3118
3119 fn from_v6(addr: Self::V6) -> Self {
3121 addr.into()
3122 }
3123}
3124
3125macro_rules! impl_ip_addr_witness {
3126 ($witness:ident) => {
3127 impl IpAddrWitness for $witness<IpAddr> {
3128 type V4 = $witness<Ipv4Addr>;
3129 type V6 = $witness<Ipv6Addr>;
3130 }
3131 };
3132}
3133
3134impl_ip_addr_witness!(SpecifiedAddr);
3135impl_ip_addr_witness!(MulticastAddr);
3136impl_ip_addr_witness!(LinkLocalAddr);
3137
3138#[allow(missing_docs)]
3145#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
3146pub enum AddrSubnetEither<A: IpAddrWitness = SpecifiedAddr<IpAddr>> {
3147 V4(AddrSubnet<Ipv4Addr, A::V4>),
3148 V6(AddrSubnet<Ipv6Addr, A::V6>),
3149}
3150
3151impl<A: IpAddrWitness> AddrSubnetEither<A> {
3152 #[inline]
3158 pub fn new(addr: IpAddr, prefix: u8) -> Result<AddrSubnetEither<A>, AddrSubnetError> {
3159 Ok(match addr {
3160 IpAddr::V4(addr) => AddrSubnetEither::V4(AddrSubnet::new(addr, prefix)?),
3161 IpAddr::V6(addr) => AddrSubnetEither::V6(AddrSubnet::new(addr, prefix)?),
3162 })
3163 }
3164
3165 #[inline]
3175 pub unsafe fn new_unchecked(addr: IpAddr, prefix: u8) -> Self {
3176 match addr {
3177 IpAddr::V4(addr) => {
3178 AddrSubnetEither::V4(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3179 }
3180 IpAddr::V6(addr) => {
3181 AddrSubnetEither::V6(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3182 }
3183 }
3184 }
3185
3186 pub fn addr(&self) -> A {
3188 match self {
3189 AddrSubnetEither::V4(v4) => v4.addr.into(),
3190 AddrSubnetEither::V6(v6) => v6.addr.into(),
3191 }
3192 }
3193
3194 #[inline]
3196 pub fn addr_prefix(&self) -> (A, u8) {
3197 match self {
3198 AddrSubnetEither::V4(v4) => (v4.addr.into(), v4.subnet.prefix),
3199 AddrSubnetEither::V6(v6) => (v6.addr.into(), v6.subnet.prefix),
3200 }
3201 }
3202
3203 #[inline]
3205 pub fn addr_subnet(&self) -> (A, SubnetEither) {
3206 match self {
3207 AddrSubnetEither::V4(v4) => (v4.addr.into(), SubnetEither::V4(v4.subnet)),
3208 AddrSubnetEither::V6(v6) => (v6.addr.into(), SubnetEither::V6(v6.subnet)),
3209 }
3210 }
3211}
3212
3213impl<S: IpAddress, A: IpAddressWitness<S> + Copy> From<AddrSubnet<S, A>>
3214 for AddrSubnetEither<A::IpAddrWitness>
3215{
3216 #[inline]
3217 fn from(addr_sub: AddrSubnet<S, A>) -> AddrSubnetEither<A::IpAddrWitness> {
3218 let (addr, sub) = addr_sub.addr_subnet();
3219 AddrSubnetEither::new(addr.get().to_ip_addr(), sub.prefix()).unwrap()
3230 }
3231}
3232
3233impl<A> Display for AddrSubnetEither<A>
3234where
3235 A: IpAddrWitness,
3236 A::V4: Display,
3237 A::V6: Display,
3238{
3239 #[inline]
3240 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
3241 match self {
3242 Self::V4(a) => write!(f, "{}", a),
3243 Self::V6(a) => write!(f, "{}", a),
3244 }
3245 }
3246}
3247
3248pub trait GenericOverIp<NewIp: Ip> {
3267 type Type;
3270}
3271
3272pub struct IpInvariant<T>(pub T);
3277
3278impl<T> IpInvariant<T> {
3279 pub fn into_inner(self) -> T {
3281 self.0
3282 }
3283}
3284
3285impl<I: Ip, T> GenericOverIp<I> for IpInvariant<T> {
3286 type Type = Self;
3287}
3288
3289impl<I: Ip> GenericOverIp<I> for core::convert::Infallible {
3290 type Type = Self;
3291}
3292
3293#[derive(GenericOverIp, Default, Debug, PartialOrd, Ord, Eq, PartialEq, Hash)]
3295#[generic_over_ip(I, Ip)]
3296pub struct IpMarked<I: Ip, T> {
3297 inner: T,
3298 _marker: IpVersionMarker<I>,
3299}
3300
3301impl<I: Ip, T> Deref for IpMarked<I, T> {
3302 type Target = T;
3303
3304 fn deref(&self) -> &Self::Target {
3305 self.as_ref()
3306 }
3307}
3308
3309impl<I: Ip, T> DerefMut for IpMarked<I, T> {
3310 fn deref_mut(&mut self) -> &mut Self::Target {
3311 self.as_mut()
3312 }
3313}
3314impl<I: Ip, T> AsRef<T> for IpMarked<I, T> {
3315 fn as_ref(&self) -> &T {
3316 &self.inner
3317 }
3318}
3319
3320impl<I: Ip, T> AsMut<T> for IpMarked<I, T> {
3321 fn as_mut(&mut self) -> &mut T {
3322 &mut self.inner
3323 }
3324}
3325
3326impl<I: Ip, T> IpMarked<I, T> {
3327 pub fn new(inner: T) -> Self {
3329 Self { inner, _marker: IpVersionMarker::<I>::new() }
3330 }
3331
3332 pub fn into_inner(self) -> T {
3334 let Self { inner, _marker } = self;
3335 inner
3336 }
3337
3338 pub fn get(&self) -> &T {
3340 self.as_ref()
3341 }
3342
3343 pub fn get_mut(&mut self) -> &mut T {
3345 self.as_mut()
3346 }
3347}
3348
3349macro_rules! for_each_tuple_ {
3351 ( $m:ident !! ) => ( $m! { });
3352 ( $m:ident !! $h:ident, $($t:ident,)* ) => (
3353 $m! { $h $($t)* }
3354 for_each_tuple_! { $m !! $($t,)* }
3355 );
3356 }
3357
3358macro_rules! for_each_tuple {
3360 ($m:ident) => {
3361 for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, }
3362 };
3363}
3364
3365macro_rules! ip_generic_tuple {
3367 () => {
3368 impl<I: Ip> GenericOverIp<I> for () {
3369 type Type = Self;
3370 }
3371 };
3372 ( $name0:ident $($name:ident)* ) => (
3373 impl<P: Ip, $name0: GenericOverIp<P>, $($name: GenericOverIp<P>,)*>
3374 GenericOverIp<P> for ($name0, $($name,)*) {
3375 type Type = ($name0::Type, $($name::Type,)*);
3376 }
3377 );
3378 }
3379
3380for_each_tuple!(ip_generic_tuple);
3381
3382macro_rules! ip_generic {
3383 ( $type:ident < $($params:ident),* >) => {
3384 impl<IpType: Ip, $($params: GenericOverIp<IpType>),*>
3385 GenericOverIp<IpType> for $type<$($params),*> {
3386 type Type = $type<$($params::Type),*>;
3387 }
3388 };
3389 ( $type:ident) => {
3390 impl<IpType: Ip> GenericOverIp<IpType> for $type {
3391 type Type = Self;
3392 }
3393 }
3394}
3395
3396ip_generic!(bool);
3398ip_generic!(isize);
3399ip_generic!(i8);
3400ip_generic!(i16);
3401ip_generic!(i32);
3402ip_generic!(i64);
3403ip_generic!(usize);
3404ip_generic!(u8);
3405ip_generic!(u16);
3406ip_generic!(u32);
3407ip_generic!(u64);
3408ip_generic!(Option<T>);
3409ip_generic!(Result<R, E>);
3410#[cfg(feature = "std")]
3411ip_generic!(Vec<T>);
3412
3413impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s T
3414where
3415 T::Type: 's,
3416{
3417 type Type = &'s T::Type;
3418}
3419
3420impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s mut T
3421where
3422 T::Type: 's,
3423{
3424 type Type = &'s mut T::Type;
3425}
3426
3427#[cfg(test)]
3428mod tests {
3429 use super::*;
3430 use test_case::test_case;
3431
3432 #[test]
3433 fn test_map_ip_associated_constant() {
3434 fn get_loopback_address<I: Ip>() -> SpecifiedAddr<I::Addr> {
3435 I::map_ip((), |()| Ipv4::LOOPBACK_ADDRESS, |()| Ipv6::LOOPBACK_ADDRESS)
3436 }
3437
3438 assert_eq!(get_loopback_address::<Ipv4>(), Ipv4::LOOPBACK_ADDRESS);
3439 assert_eq!(get_loopback_address::<Ipv6>(), Ipv6::LOOPBACK_ADDRESS);
3440 }
3441
3442 #[test]
3443 fn test_map_ip_different_behavior() {
3444 fn filter_v4<I: Ip>(addr: I::Addr) -> Option<I::Addr> {
3445 I::map_ip(addr, |addr| Some(addr), |_addr| None)
3446 }
3447
3448 assert_eq!(filter_v4::<Ipv4>(*Ipv4::LOOPBACK_ADDRESS), Some(*Ipv4::LOOPBACK_ADDRESS));
3449 assert_eq!(filter_v4::<Ipv6>(*Ipv6::LOOPBACK_ADDRESS), None);
3450 }
3451
3452 #[test]
3453 fn test_map_ip_extension_trait_fn() {
3454 trait FakeIpExt: Ip {
3455 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr;
3456 }
3457
3458 impl FakeIpExt for Ipv4 {
3459 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3460 let Ipv4Addr(mut bytes) = a;
3461 bytes.reverse();
3462 Ipv4Addr(bytes)
3463 }
3464 }
3465 impl FakeIpExt for Ipv6 {
3466 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3467 let Ipv6Addr(mut bytes) = a;
3468 bytes.reverse();
3469 Ipv6Addr(bytes)
3470 }
3471 }
3472
3473 fn reverse_bytes<A: IpAddress>(addr: A) -> A
3474 where
3475 A::Version: FakeIpExt,
3476 {
3477 A::Version::map_ip(addr, Ipv4::reverse_addr_bytes, Ipv6::reverse_addr_bytes)
3478 }
3479
3480 assert_eq!(reverse_bytes(Ipv4Addr([1, 2, 3, 4])), Ipv4Addr([4, 3, 2, 1]));
3481 assert_eq!(
3482 reverse_bytes(Ipv6Addr([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])),
3483 Ipv6Addr([16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
3484 );
3485 }
3486
3487 #[test]
3488 fn test_map_ip_extension_trait_associated_type() {
3489 trait FakeIpExt: Ip {
3490 type PackedInt;
3491 }
3492 impl FakeIpExt for Ipv4 {
3493 type PackedInt = u32;
3494 }
3495 impl FakeIpExt for Ipv6 {
3496 type PackedInt = u128;
3497 }
3498
3499 #[derive(Debug, PartialEq)]
3500 struct Int<T>(T);
3501
3502 impl<T, I: FakeIpExt> GenericOverIp<I> for Int<T> {
3503 type Type = Int<I::PackedInt>;
3504 }
3505
3506 fn from_be_bytes<A: IpAddress>(addr: A) -> Int<<A::Version as FakeIpExt>::PackedInt>
3507 where
3508 A::Version: FakeIpExt,
3509 {
3510 A::Version::map_ip(
3511 addr,
3512 |Ipv4Addr(bytes)| Int(<Ipv4 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3513 |Ipv6Addr(bytes)| Int(<Ipv6 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3514 )
3515 }
3516
3517 assert_eq!(from_be_bytes(Ipv4::LOOPBACK_ADDRESS.get()), Int(0x7f000001u32));
3518 assert_eq!(from_be_bytes(Ipv6::LOOPBACK_ADDRESS.get()), Int(1u128));
3519 }
3520
3521 #[test]
3522 fn map_ip_twice() {
3523 struct FooV4 {
3524 field: Ipv4Addr,
3525 }
3526
3527 impl Default for FooV4 {
3528 fn default() -> Self {
3529 Self { field: Ipv4::UNSPECIFIED_ADDRESS }
3530 }
3531 }
3532
3533 struct FooV6 {
3534 field: Ipv6Addr,
3535 }
3536
3537 impl Default for FooV6 {
3538 fn default() -> Self {
3539 Self { field: Ipv6::UNSPECIFIED_ADDRESS }
3540 }
3541 }
3542
3543 trait IpExt {
3544 type Foo: Default;
3545 }
3546
3547 impl IpExt for Ipv4 {
3548 type Foo = FooV4;
3549 }
3550
3551 impl IpExt for Ipv6 {
3552 type Foo = FooV6;
3553 }
3554
3555 #[derive(GenericOverIp)]
3556 #[generic_over_ip(I, Ip)]
3557 struct Foo<I: IpExt>(I::Foo);
3558
3559 fn do_something<I: Ip + IpExt>(
3560 foo: Foo<I>,
3561 extra_foo: Foo<I>,
3562 captured_foo: Foo<I>,
3563 ) -> I::Addr {
3564 let addr: I::Addr = map_ip_twice!(I, foo, |Foo(foo)| { foo.field });
3565
3566 let _: I::Addr =
3569 map_ip_twice!(<<I as Ip>::Addr as IpAddress>::Version, extra_foo, |Foo(foo)| {
3570 let _: &Foo<I> = &captured_foo;
3574 foo.field
3575 });
3576
3577 addr
3578 }
3579
3580 assert_eq!(
3581 do_something(
3582 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3583 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3584 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS })
3585 ),
3586 Ipv4::UNSPECIFIED_ADDRESS
3587 );
3588 assert_eq!(
3589 do_something(
3590 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3591 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3592 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS })
3593 ),
3594 Ipv6::UNSPECIFIED_ADDRESS
3595 );
3596
3597 fn do_something_with_default_type_alias_shadowing<I: Ip>() -> (I::Addr, IpVersion) {
3598 let (field, IpInvariant(version)) = map_ip_twice!(I, (), |()| {
3599 let foo: Foo<I> = Foo(<I as IpExt>::Foo::default());
3602 (foo.0.field, IpInvariant(I::VERSION))
3603 },);
3604 (field, version)
3605 }
3606
3607 fn do_something_with_type_alias<I: Ip>() -> (I::Addr, IpVersion) {
3608 #[allow(dead_code)]
3611 type IpAlias = usize;
3612
3613 let (field, IpInvariant(version)) = map_ip_twice!(I as IpAlias, (), |()| {
3614 let foo: Foo<IpAlias> = Foo(<IpAlias as IpExt>::Foo::default());
3618 (foo.0.field, IpInvariant(IpAlias::VERSION))
3619 },);
3620 (field, version)
3621 }
3622
3623 assert_eq!(
3624 do_something_with_default_type_alias_shadowing::<Ipv4>(),
3625 (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3626 );
3627 assert_eq!(
3628 do_something_with_default_type_alias_shadowing::<Ipv6>(),
3629 (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3630 );
3631 assert_eq!(
3632 do_something_with_type_alias::<Ipv4>(),
3633 (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3634 );
3635 assert_eq!(
3636 do_something_with_type_alias::<Ipv6>(),
3637 (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3638 );
3639 }
3640
3641 #[test]
3642 fn test_loopback_unicast() {
3643 assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
3647 assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
3648 }
3649
3650 #[test]
3651 fn test_specified() {
3652 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_specified());
3659 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_specified());
3660
3661 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_unicast());
3664
3665 let unicast = Ipv6Addr([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
3666 assert!(unicast.is_unicast());
3667 assert!(unicast.is_specified());
3668
3669 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_multicast());
3672 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_multicast());
3673
3674 let multicast = Ipv4::MULTICAST_SUBNET.network;
3675 assert!(multicast.is_multicast());
3676 assert!(multicast.is_specified());
3677 let multicast = Ipv6::MULTICAST_SUBNET.network;
3678 assert!(multicast.is_multicast());
3679 assert!(multicast.is_specified());
3680
3681 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_link_local());
3684 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_link_local());
3685
3686 let link_local = Ipv4::LINK_LOCAL_UNICAST_SUBNET.network;
3687 assert!(link_local.is_link_local());
3688 assert!(link_local.is_specified());
3689 let link_local = Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network;
3690 assert!(link_local.is_link_local());
3691 assert!(link_local.is_specified());
3692 let link_local = Ipv6::LINK_LOCAL_UNICAST_SUBNET.network;
3693 assert!(link_local.is_link_local());
3694 assert!(link_local.is_specified());
3695 let mut link_local = Ipv6::MULTICAST_SUBNET.network;
3696 link_local.0[1] = 0x02;
3697 assert!(link_local.is_link_local());
3698 assert!(link_local.is_specified());
3699 assert!(Ipv6::LOOPBACK_ADDRESS.is_link_local());
3700 }
3701
3702 #[test]
3703 fn test_link_local() {
3704 assert!(Ipv4::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3706 assert!(Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network.is_link_local());
3707
3708 assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3710 assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_unicast_link_local());
3711 let mut addr = Ipv6::MULTICAST_SUBNET.network;
3712 for flags in 0..=0x0F {
3713 addr.0[1] = (flags << 4) | 0x02;
3715 assert!(addr.is_link_local());
3718 assert!(!addr.is_unicast_link_local());
3719 }
3720
3721 let mut addr = Ipv6::LOOPBACK_ADDRESS.get();
3725 addr.0[1] = 0x02;
3727 assert!(!addr.is_link_local());
3728 }
3729
3730 #[test]
3731 fn test_subnet_new() {
3732 assert_eq!(
3733 Subnet::new(Ipv4Addr::new([255, 255, 255, 255]), 32).unwrap(),
3734 Subnet { network: Ipv4Addr::new([255, 255, 255, 255]), prefix: 32 },
3735 );
3736 assert_eq!(
3738 Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 33),
3739 Err(SubnetError::PrefixTooLong)
3740 );
3741 assert_eq!(
3742 Subnet::from_host(Ipv4Addr::new([255, 255, 255, 255]), 33),
3743 Err(PrefixTooLongError)
3744 );
3745 assert_eq!(Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 8), Err(SubnetError::HostBitsSet));
3747 assert_eq!(
3749 Subnet::from_host(Ipv4Addr::new([255, 255, 0, 0]), 8),
3750 Ok(Subnet { network: Ipv4Addr::new([255, 0, 0, 0]), prefix: 8 })
3751 );
3752
3753 assert_eq!(
3754 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32).unwrap(),
3755 AddrSubnet {
3756 addr: SpecifiedAddr(Ipv4Addr::new([1, 2, 3, 4])),
3757 subnet: Subnet { network: Ipv4Addr::new([1, 2, 3, 4]), prefix: 32 }
3758 }
3759 );
3760 assert!(
3764 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::UNSPECIFIED_ADDRESS, 16)
3765 == Err(AddrSubnetError::InvalidWitness)
3766 );
3767 assert!(
3768 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv6::UNSPECIFIED_ADDRESS, 64)
3769 == Err(AddrSubnetError::InvalidWitness)
3770 );
3771 assert!(
3773 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 33)
3774 == Err(AddrSubnetError::PrefixTooLong)
3775 );
3776 assert!(
3777 AddrSubnet::<_, SpecifiedAddr<_>>::new(
3778 Ipv6Addr::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
3779 129,
3780 ) == Err(AddrSubnetError::PrefixTooLong)
3781 );
3782 assert!(
3784 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::LIMITED_BROADCAST_ADDRESS.get(), 16)
3785 == Err(AddrSubnetError::NotUnicastInSubnet)
3786 );
3787 assert!(
3789 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([192, 168, 255, 255]), 16)
3790 == Err(AddrSubnetError::NotUnicastInSubnet)
3791 );
3792 assert!(
3794 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([224, 0, 0, 1]), 16)
3795 == Err(AddrSubnetError::NotUnicastInSubnet)
3796 );
3797 assert!(
3798 AddrSubnet::<_, SpecifiedAddr<_>>::new(
3799 Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
3800 64,
3801 ) == Err(AddrSubnetError::NotUnicastInSubnet)
3802 );
3803
3804 assert!(
3808 AddrSubnet::<_, LinkLocalAddr<Ipv4Addr>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32)
3809 == Err(AddrSubnetError::InvalidWitness)
3810 );
3811 }
3812
3813 #[test]
3814 fn test_is_unicast_in_subnet() {
3815 let subnet =
3817 Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).expect("1.2.0.0/16 is a valid subnet");
3818 assert!(Ipv4Addr::new([1, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3819 assert!(!Ipv4Addr::new([2, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3820
3821 let subnet =
3822 Subnet::new(Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 64)
3823 .expect("1::/64 is a valid subnet");
3824 assert!(Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3825 .is_unicast_in_subnet(&subnet));
3826 assert!(!Ipv6Addr::from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3827 .is_unicast_in_subnet(&subnet));
3828
3829 assert!(!Ipv4::UNSPECIFIED_ADDRESS
3831 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 16).unwrap()));
3832 assert!(!Ipv6::UNSPECIFIED_ADDRESS
3833 .is_unicast_in_subnet(&Subnet::new(Ipv6::UNSPECIFIED_ADDRESS, 64).unwrap()));
3834 assert!(!Ipv4::UNSPECIFIED_ADDRESS
3837 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 31).unwrap()));
3838 assert!(!Ipv4::UNSPECIFIED_ADDRESS
3839 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 32).unwrap()));
3840 assert!(!Ipv4Addr::new([1, 2, 0, 0])
3842 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap()));
3843 assert!(Ipv4Addr::new([1, 2, 3, 0])
3845 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 31).unwrap()));
3846 assert!(Ipv4Addr::new([1, 2, 3, 0])
3847 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 32).unwrap()));
3848 assert!(!Ipv4::LIMITED_BROADCAST_ADDRESS
3850 .get()
3851 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([128, 0, 0, 0]), 1).unwrap()));
3852 assert!(!Ipv4Addr::new([1, 2, 255, 255])
3854 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap()));
3855 assert!(Ipv4Addr::new([1, 2, 255, 255])
3857 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 254]), 31).unwrap()));
3858 assert!(Ipv4Addr::new([1, 2, 255, 255])
3859 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 255]), 32).unwrap()));
3860 assert!(!Ipv4Addr::new([224, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::MULTICAST_SUBNET));
3862 assert!(!Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3863 .is_unicast_in_subnet(&Ipv6::MULTICAST_SUBNET));
3864 assert!(!Ipv4Addr::new([240, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::CLASS_E_SUBNET));
3866 }
3867
3868 macro_rules! add_mask_test {
3869 ($name:ident, $addr:ident, $from_ip:expr => {
3870 $($mask:expr => $to_ip:expr),*
3871 }) => {
3872 #[test]
3873 fn $name() {
3874 let from = $addr::from($from_ip);
3875 $(assert_eq!(from.mask($mask), $addr::from($to_ip), "(`{}`.mask({}))", from, $mask);)*
3876 }
3877 };
3878 ($name:ident, $addr:ident, $from_ip:expr => {
3879 $($mask:expr => $to_ip:expr),*,
3880 }) => {
3881 add_mask_test!($name, $addr, $from_ip => { $($mask => $to_ip),* });
3882 };
3883 }
3884
3885 add_mask_test!(v4_full_mask, Ipv4Addr, [255, 254, 253, 252] => {
3886 32 => [255, 254, 253, 252],
3887 28 => [255, 254, 253, 240],
3888 24 => [255, 254, 253, 0],
3889 20 => [255, 254, 240, 0],
3890 16 => [255, 254, 0, 0],
3891 12 => [255, 240, 0, 0],
3892 8 => [255, 0, 0, 0],
3893 4 => [240, 0, 0, 0],
3894 0 => [0, 0, 0, 0],
3895 });
3896
3897 add_mask_test!(v6_full_mask, Ipv6Addr,
3898 [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0] => {
3899 128 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0],
3900 112 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0x00, 0x00],
3901 96 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0x00, 0x00, 0x00, 0x00],
3902 80 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3903 64 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3904 48 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3905 32 => [0xFF, 0xFE, 0xFD, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3906 16 => [0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3907 8 => [0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3908 0 => [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3909 }
3910 );
3911
3912 #[test_case([255, 255, 255, 0] => Ok(24))]
3913 #[test_case([255, 255, 254, 0] => Ok(23))]
3914 #[test_case([255, 255, 253, 0] => Err(NotSubnetMaskError))]
3915 #[test_case([255, 255, 0, 255] => Err(NotSubnetMaskError))]
3916 #[test_case([255, 255, 255, 255] => Ok(32))]
3917 #[test_case([0, 0, 0, 0] => Ok(0))]
3918 #[test_case([0, 0, 0, 255] => Err(NotSubnetMaskError))]
3919 fn test_ipv4_prefix_len_try_from_subnet_mask(
3920 subnet_mask: [u8; 4],
3921 ) -> Result<u8, NotSubnetMaskError> {
3922 let subnet_mask = Ipv4Addr::from(subnet_mask);
3923 PrefixLength::<Ipv4>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
3924 }
3925
3926 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(64))]
3927 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(63))]
3928 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
3929 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 1] => Err(NotSubnetMaskError))]
3930 #[test_case([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(0))]
3931 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] => Ok(128))]
3932 #[test_case([0, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
3933 fn test_ipv6_prefix_len_try_from_subnet_mask(
3934 subnet_mask: [u8; 16],
3935 ) -> Result<u8, NotSubnetMaskError> {
3936 let subnet_mask = Ipv6Addr::from(subnet_mask);
3937 PrefixLength::<Ipv6>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
3938 }
3939
3940 #[test_case(0 => true)]
3941 #[test_case(1 => true)]
3942 #[test_case(32 => true)]
3943 #[test_case(33 => false)]
3944 #[test_case(128 => false)]
3945 #[test_case(129 => false)]
3946 #[test_case(255 => false)]
3947 fn test_ipv4_prefix_len_new(prefix_len: u8) -> bool {
3948 PrefixLength::<Ipv4>::new(prefix_len).is_ok()
3949 }
3950
3951 #[test_case(0 => true)]
3952 #[test_case(1 => true)]
3953 #[test_case(32 => true)]
3954 #[test_case(33 => true)]
3955 #[test_case(128 => true)]
3956 #[test_case(129 => false)]
3957 #[test_case(255 => false)]
3958 fn test_ipv6_prefix_len_new(prefix_len: u8) -> bool {
3959 PrefixLength::<Ipv6>::new(prefix_len).is_ok()
3960 }
3961
3962 #[test_case(0 => [0, 0, 0, 0])]
3963 #[test_case(6 => [252, 0, 0, 0])]
3964 #[test_case(16 => [255, 255, 0, 0])]
3965 #[test_case(25 => [255, 255, 255, 128])]
3966 #[test_case(32 => [255, 255, 255, 255])]
3967 fn test_ipv4_prefix_len_get_mask(prefix_len: u8) -> [u8; 4] {
3968 let Ipv4Addr(inner) = PrefixLength::<Ipv4>::new(prefix_len).unwrap().get_mask();
3969 inner
3970 }
3971
3972 #[test_case(0 => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
3973 #[test_case(6 => [0xFC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
3974 #[test_case(64 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])]
3975 #[test_case(65 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0])]
3976 #[test_case(128 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])]
3977 fn test_ipv6_prefix_len_get_mask(prefix_len: u8) -> [u8; 16] {
3978 let Ipv6Addr(inner) = PrefixLength::<Ipv6>::new(prefix_len).unwrap().get_mask();
3979 inner
3980 }
3981
3982 #[test]
3983 fn test_ipv6_solicited_node() {
3984 let addr = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
3985 let solicited = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
3986 assert_eq!(addr.to_solicited_node_address().get(), solicited);
3987 }
3988
3989 #[test]
3990 fn test_ipv6_address_types() {
3991 assert!(!Ipv6Addr::from([0; 16]).is_specified());
3992 assert!(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1]).is_loopback());
3993 let link_local = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
3994 assert!(link_local.is_link_local());
3995 assert!(link_local.is_valid_unicast());
3996 assert!(link_local.to_solicited_node_address().is_multicast());
3997 let global_unicast = Ipv6Addr::new([0x80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
3998 assert!(global_unicast.is_valid_unicast());
3999 assert!(global_unicast.to_solicited_node_address().is_multicast());
4000
4001 let multi = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
4002 assert!(multi.is_multicast());
4003 assert!(!multi.is_valid_unicast());
4004 }
4005
4006 #[test]
4007 fn test_const_witness() {
4008 assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
4011 assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
4012 assert!(Ipv4::LIMITED_BROADCAST_ADDRESS.0.is_specified());
4013 assert!(Ipv4::ALL_ROUTERS_MULTICAST_ADDRESS.0.is_multicast());
4014 assert!(Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4015 assert!(Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4016 }
4017
4018 #[test]
4019 fn test_ipv6_scope() {
4020 use Ipv6ReservedScope::*;
4021 use Ipv6Scope::*;
4022 use Ipv6UnassignedScope::*;
4023
4024 assert_eq!(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network.scope(), SiteLocal);
4026 assert_eq!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.scope(), LinkLocal);
4027 assert_eq!(Ipv6::UNSPECIFIED_ADDRESS.scope(), Global);
4028
4029 let assert_scope = |value, scope| {
4031 let mut addr = Ipv6::MULTICAST_SUBNET.network;
4032 addr.0[1] |= value;
4034 assert_eq!(addr.scope(), scope);
4035 };
4036 assert_scope(0, Reserved(Scope0));
4037 assert_scope(1, InterfaceLocal);
4038 assert_scope(2, LinkLocal);
4039 assert_scope(3, Reserved(Scope3));
4040 assert_scope(4, AdminLocal);
4041 assert_scope(5, SiteLocal);
4042 assert_scope(6, Unassigned(Scope6));
4043 assert_scope(7, Unassigned(Scope7));
4044 assert_scope(8, OrganizationLocal);
4045 assert_scope(9, Unassigned(Scope9));
4046 assert_scope(0xA, Unassigned(ScopeA));
4047 assert_scope(0xB, Unassigned(ScopeB));
4048 assert_scope(0xC, Unassigned(ScopeC));
4049 assert_scope(0xD, Unassigned(ScopeD));
4050 assert_scope(0xE, Global);
4051 assert_scope(0xF, Reserved(ScopeF));
4052 }
4053
4054 #[test]
4055 fn test_ipv6_multicast_scope_id() {
4056 const ALL_SCOPES: &[Ipv6Scope] = &[
4057 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope0),
4058 Ipv6Scope::InterfaceLocal,
4059 Ipv6Scope::LinkLocal,
4060 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope3),
4061 Ipv6Scope::AdminLocal,
4062 Ipv6Scope::SiteLocal,
4063 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope6),
4064 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope7),
4065 Ipv6Scope::OrganizationLocal,
4066 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope9),
4067 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeA),
4068 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeB),
4069 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeC),
4070 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeD),
4071 Ipv6Scope::Global,
4072 Ipv6Scope::Reserved(Ipv6ReservedScope::ScopeF),
4073 ];
4074 for (i, a) in ALL_SCOPES.iter().enumerate() {
4075 assert_eq!(a.multicast_scope_id(), i.try_into().unwrap());
4076 }
4077 }
4078
4079 #[test]
4080 fn test_ipv4_embedded() {
4081 assert_eq!(
4084 Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_compatible(),
4085 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4])
4086 );
4087 assert_eq!(
4088 Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_mapped().get(),
4089 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]),
4090 );
4091
4092 let compatible = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4]);
4095 let mapped = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]);
4096 let not_embedded = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 1, 2, 3, 4]);
4097 let v4 = Ipv4Addr::new([1, 2, 3, 4]);
4098
4099 assert_eq!(compatible.to_ipv4_compatible(), Some(v4));
4100 assert_eq!(compatible.to_ipv4_mapped(), None);
4101
4102 assert_eq!(mapped.to_ipv4_compatible(), None);
4103 assert_eq!(mapped.to_ipv4_mapped(), Some(v4));
4104
4105 assert_eq!(not_embedded.to_ipv4_compatible(), None);
4106 assert_eq!(not_embedded.to_ipv4_mapped(), None);
4107
4108 assert_eq!(
4109 NonMappedAddr::new(compatible),
4110 Some(unsafe { NonMappedAddr::new_unchecked(compatible) })
4111 );
4112 assert_eq!(NonMappedAddr::new(mapped), None);
4113 assert_eq!(
4114 NonMappedAddr::new(not_embedded),
4115 Some(unsafe { NonMappedAddr::new_unchecked(not_embedded) })
4116 );
4117 assert_eq!(NonMappedAddr::new(v4), Some(unsafe { NonMappedAddr::new_unchecked(v4) }));
4118 }
4119
4120 #[test]
4121 fn test_common_prefix_len_ipv6() {
4122 let ip1 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4123 let ip2 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4124 let ip3 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4125 let ip4 = Ipv6Addr::from([0xFF, 0xFF, 0xC0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4126 let compare_with_ip1 = |target, expect| {
4127 assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4128 };
4129 compare_with_ip1(ip1, 128);
4130 compare_with_ip1(ip2, 0);
4131 compare_with_ip1(ip3, 24);
4132 compare_with_ip1(ip4, 17);
4133 }
4134
4135 #[test]
4136 fn test_common_prefix_len_ipv4() {
4137 let ip1 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0]);
4138 let ip2 = Ipv4Addr::new([0, 0, 0, 0]);
4139 let ip3 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0xFF]);
4140 let ip4 = Ipv4Addr::new([0xFF, 0xFF, 0xC0, 0x20]);
4141 let compare_with_ip1 = |target, expect| {
4142 assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4143 };
4144 compare_with_ip1(ip1, 32);
4145 compare_with_ip1(ip2, 0);
4146 compare_with_ip1(ip3, 24);
4147 compare_with_ip1(ip4, 17);
4148 }
4149
4150 #[test]
4151 fn test_ipv6_display() {
4152 fn test_one(addr: Ipv6Addr, expect: Option<&str>) {
4156 let formatted = format!("{}", addr);
4157 if let Some(expect) = expect {
4158 assert_eq!(formatted, expect);
4159 }
4160
4161 let formatted_std = format!("{}", std::net::Ipv6Addr::from(addr.segments()));
4171 assert_eq!(formatted, formatted_std);
4172 }
4173
4174 test_one(Ipv6::UNSPECIFIED_ADDRESS, Some("::"));
4175 test_one(*Ipv6::LOOPBACK_ADDRESS, Some("::1"));
4176 test_one(Ipv6::MULTICAST_SUBNET.network, Some("ff00::"));
4177 test_one(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network, Some("fe80::"));
4178 test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4179 test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4180 test_one(*Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::2"));
4181 test_one(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network, Some("fec0::"));
4182 test_one(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), Some("1::"));
4183 test_one(Ipv6Addr::new([0, 0, 0, 1, 2, 3, 4, 5]), Some("::1:2:3:4:5"));
4184
4185 for byte in 0u8..=255 {
4190 test_one(
4191 Ipv6Addr::new([
4192 u16::from(byte & 0b1),
4193 u16::from((byte & 0b10) >> 1),
4194 u16::from((byte & 0b100) >> 2),
4195 u16::from((byte & 0b1000) >> 3),
4196 u16::from((byte & 0b10000) >> 4),
4197 u16::from((byte & 0b100000) >> 5),
4198 u16::from((byte & 0b1000000) >> 6),
4199 u16::from((byte & 0b10000000) >> 7),
4200 ]),
4201 None,
4202 );
4203 }
4204 }
4205
4206 #[test_case(Ipv4::UNSPECIFIED_ADDRESS, Ipv4AddressClass::A; "first_class_a")]
4207 #[test_case(Ipv4Addr::new([127, 255, 255, 255]), Ipv4AddressClass::A; "last_class_a")]
4208 #[test_case(Ipv4Addr::new([128, 0, 0, 0]), Ipv4AddressClass::B; "first_class_b")]
4209 #[test_case(Ipv4Addr::new([191, 255, 255, 255]), Ipv4AddressClass::B; "last_class_b")]
4210 #[test_case(Ipv4Addr::new([192, 0, 0, 0]), Ipv4AddressClass::C; "first_class_c")]
4211 #[test_case(Ipv4Addr::new([223, 255, 255, 255]), Ipv4AddressClass::C; "last_class_c")]
4212 #[test_case(Ipv4Addr::new([224, 0, 0, 0]), Ipv4AddressClass::D; "first_class_d")]
4213 #[test_case(Ipv4Addr::new([239, 255, 255, 255]), Ipv4AddressClass::D; "last_class_d")]
4214 #[test_case(Ipv4Addr::new([240, 0, 0, 0]), Ipv4AddressClass::E; "first_class_e")]
4215 #[test_case(Ipv4Addr::new([255, 255, 255, 255]), Ipv4AddressClass::E; "last_class_e")]
4216 fn ipv4addr_class(addr: Ipv4Addr, class: Ipv4AddressClass) {
4217 assert_eq!(addr.class(), class)
4218 }
4219
4220 #[test_case(
4221 Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 24).unwrap(),
4222 Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap()
4223 ; "ipv4_same_prefix")]
4224 #[test_case(
4225 Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap(),
4226 Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 32).unwrap()
4227 ; "ipv4_by_prefix")]
4228 #[test_case(
4229 Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4230 Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap()
4231 ; "ipv6_same_prefix")]
4232 #[test_case(
4233 Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4234 Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 128).unwrap()
4235 ; "ipv6_by_prefix")]
4236 fn subnet_ord<A: core::cmp::Ord>(a: Subnet<A>, b: Subnet<A>) {
4237 assert!(a < b);
4238 }
4239
4240 #[cfg(feature = "std")]
4241 mod std_tests {
4242 use super::*;
4243
4244 #[test]
4245 fn test_conversions() {
4246 let v4 = Ipv4Addr::new([127, 0, 0, 1]);
4247 let v6 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
4248 let std_v4 = net::Ipv4Addr::new(127, 0, 0, 1);
4249 let std_v6 = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
4250
4251 let converted: IpAddr = net::IpAddr::V4(std_v4).into();
4252 assert_eq!(converted, IpAddr::V4(v4));
4253 let converted: IpAddr = net::IpAddr::V6(std_v6).into();
4254 assert_eq!(converted, IpAddr::V6(v6));
4255
4256 let converted: net::IpAddr = IpAddr::V4(v4).into();
4257 assert_eq!(converted, net::IpAddr::V4(std_v4));
4258 let converted: net::IpAddr = IpAddr::V6(v6).into();
4259 assert_eq!(converted, net::IpAddr::V6(std_v6));
4260
4261 let converted: Ipv4Addr = std_v4.into();
4262 assert_eq!(converted, v4);
4263 let converted: Ipv6Addr = std_v6.into();
4264 assert_eq!(converted, v6);
4265
4266 let converted: net::Ipv4Addr = v4.into();
4267 assert_eq!(converted, std_v4);
4268 let converted: net::Ipv6Addr = v6.into();
4269 assert_eq!(converted, std_v6);
4270 }
4271 }
4272}
4273
4274#[cfg(test)]
4276mod macro_test {
4277 use super::*;
4278
4279 fn assert_ip_generic_is<T, I, Other>()
4281 where
4282 I: Ip,
4283 T: GenericOverIp<I, Type = Other>,
4284 {
4285 }
4288
4289 macro_rules! assert_ip_generic {
4290 ($name:ident, Ip $(,$($param:ident),*)?) => {
4291 assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4292 assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4293 assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4294 assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4295 };
4296 ($name:ident, IpAddress $(,$($param:ident),*)?) => {
4297 assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4298 assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4299 assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4300 assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4301 };
4302 ($name:ident $(,$($param:ident),*)?) => {
4303 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4304 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4305 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4306 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4307 };
4308 }
4309
4310 #[test]
4311 fn struct_with_ip_version_parameter() {
4312 #[allow(dead_code)]
4313 #[derive(GenericOverIp)]
4314 #[generic_over_ip(I, Ip)]
4315 struct Generic<I: Ip> {
4316 addr: I::Addr,
4317 }
4318
4319 assert_ip_generic!(Generic, Ip);
4320 }
4321
4322 #[test]
4323 fn struct_with_unbounded_ip_version_parameter() {
4324 #[allow(dead_code)]
4325 #[derive(GenericOverIp)]
4326 #[generic_over_ip(I, Ip)]
4327 struct Generic<I> {
4328 addr: core::marker::PhantomData<I>,
4329 }
4330
4331 assert_ip_generic!(Generic, Ip);
4332 }
4333
4334 #[test]
4335 fn struct_with_ip_address_parameter() {
4336 #[allow(dead_code)]
4337 #[derive(GenericOverIp)]
4338 #[generic_over_ip(A, IpAddress)]
4339 struct Generic<A: IpAddress> {
4340 addr: A,
4341 }
4342
4343 assert_ip_generic!(Generic, IpAddress);
4344 }
4345
4346 #[test]
4347 fn struct_with_unbounded_ip_address_parameter() {
4348 #[allow(dead_code)]
4349 #[derive(GenericOverIp)]
4350 #[generic_over_ip(A, IpAddress)]
4351 struct Generic<A> {
4352 addr: A,
4353 }
4354
4355 assert_ip_generic!(Generic, IpAddress);
4356 }
4357
4358 #[test]
4359 fn struct_with_generic_over_ip_parameter() {
4360 #[derive(GenericOverIp)]
4361 #[generic_over_ip(I, Ip)]
4362 struct InnerGeneric<I: Ip> {
4363 addr: I::Addr,
4364 }
4365
4366 #[derive(GenericOverIp)]
4367 #[generic_over_ip(T, GenericOverIp)]
4368 struct Generic<T> {
4369 foo: T,
4370 }
4371
4372 fn do_something<I: Ip>(g: Generic<InnerGeneric<I>>) {
4373 I::map_ip(
4374 g,
4375 |g| {
4376 let _: Ipv4Addr = g.foo.addr;
4377 },
4378 |g| {
4379 let _: Ipv6Addr = g.foo.addr;
4380 },
4381 )
4382 }
4383
4384 do_something::<Ipv4>(Generic { foo: InnerGeneric { addr: Ipv4::UNSPECIFIED_ADDRESS } });
4385
4386 do_something::<Ipv6>(Generic { foo: InnerGeneric { addr: Ipv6::UNSPECIFIED_ADDRESS } });
4387 }
4388
4389 #[test]
4390 fn enum_with_ip_version_parameter() {
4391 #[allow(dead_code)]
4392 #[derive(GenericOverIp)]
4393 #[generic_over_ip(I, Ip)]
4394 enum Generic<I: Ip> {
4395 A(I::Addr),
4396 B(I::Addr),
4397 }
4398
4399 assert_ip_generic!(Generic, Ip);
4400 }
4401
4402 #[test]
4403 fn enum_with_unbounded_ip_version_parameter() {
4404 #[allow(dead_code)]
4405 #[derive(GenericOverIp)]
4406 #[generic_over_ip(I, Ip)]
4407 enum Generic<I> {
4408 A(core::marker::PhantomData<I>),
4409 B(core::marker::PhantomData<I>),
4410 }
4411
4412 assert_ip_generic!(Generic, Ip);
4413 }
4414
4415 #[test]
4416 fn enum_with_ip_address_parameter() {
4417 #[allow(dead_code)]
4418 #[derive(GenericOverIp)]
4419 #[generic_over_ip(A, IpAddress)]
4420 enum Generic<A: IpAddress> {
4421 A(A),
4422 B(A),
4423 }
4424
4425 assert_ip_generic!(Generic, IpAddress);
4426 }
4427
4428 #[test]
4429 fn enum_with_unbounded_ip_address_parameter() {
4430 #[allow(dead_code)]
4431 #[derive(GenericOverIp)]
4432 #[generic_over_ip(A, IpAddress)]
4433 enum Generic<A> {
4434 A(A),
4435 B(A),
4436 }
4437
4438 assert_ip_generic!(Generic, IpAddress);
4439 }
4440
4441 #[test]
4442 fn struct_with_ip_version_and_other_parameters() {
4443 #[allow(dead_code)]
4444 #[derive(GenericOverIp)]
4445 #[generic_over_ip(I, Ip)]
4446 struct AddrAndDevice<I: Ip, D> {
4447 addr: I::Addr,
4448 device: D,
4449 }
4450 struct Device;
4451
4452 assert_ip_generic!(AddrAndDevice, Ip, Device);
4453 }
4454
4455 #[test]
4456 fn enum_with_ip_version_and_other_parameters() {
4457 #[allow(dead_code)]
4458 #[derive(GenericOverIp)]
4459 #[generic_over_ip(I, Ip)]
4460 enum AddrOrDevice<I: Ip, D> {
4461 Addr(I::Addr),
4462 Device(D),
4463 }
4464 struct Device;
4465
4466 assert_ip_generic!(AddrOrDevice, Ip, Device);
4467 }
4468
4469 #[test]
4470 fn struct_with_ip_address_and_other_parameters() {
4471 #[allow(dead_code)]
4472 #[derive(GenericOverIp)]
4473 #[generic_over_ip(A, IpAddress)]
4474 struct AddrAndDevice<A: IpAddress, D> {
4475 addr: A,
4476 device: D,
4477 }
4478 struct Device;
4479
4480 assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4481 }
4482
4483 #[test]
4484 fn struct_with_unbounded_ip_address_and_other_parameters() {
4485 #[allow(dead_code)]
4486 #[derive(GenericOverIp)]
4487 #[generic_over_ip(A, IpAddress)]
4488 struct AddrAndDevice<A, D> {
4489 addr: A,
4490 device: D,
4491 }
4492 struct Device;
4493
4494 assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4495 }
4496
4497 #[test]
4498 fn enum_with_ip_address_and_other_parameters() {
4499 #[allow(dead_code)]
4500 #[derive(GenericOverIp, Debug, PartialEq)]
4501 #[generic_over_ip(A, IpAddress)]
4502 enum AddrOrDevice<A: IpAddress, D> {
4503 Addr(A),
4504 Device(D),
4505 }
4506 struct Device;
4507
4508 assert_ip_generic!(AddrOrDevice, IpAddress, Device);
4509 }
4510
4511 #[test]
4512 fn struct_invariant_over_ip() {
4513 #[allow(dead_code)]
4514 #[derive(GenericOverIp)]
4515 #[generic_over_ip()]
4516 struct Invariant(usize);
4517
4518 assert_ip_generic!(Invariant);
4519 }
4520
4521 #[test]
4522 fn enum_invariant_over_ip() {
4523 #[allow(dead_code)]
4524 #[derive(GenericOverIp)]
4525 #[generic_over_ip()]
4526 enum Invariant {
4527 Usize(usize),
4528 }
4529
4530 assert_ip_generic!(Invariant);
4531 }
4532
4533 #[test]
4534 fn struct_invariant_over_ip_with_other_params() {
4535 #[allow(dead_code)]
4536 #[derive(GenericOverIp)]
4537 #[generic_over_ip()]
4538 struct Invariant<B, C, D>(B, C, D);
4539
4540 assert_ip_generic!(Invariant, usize, bool, char);
4541 }
4542
4543 #[test]
4544 fn enum_invariant_over_ip_with_other_params() {
4545 #[allow(dead_code)]
4546 #[derive(GenericOverIp)]
4547 #[generic_over_ip()]
4548 enum Invariant<A, B, C> {
4549 A(A),
4550 B(B),
4551 C(C),
4552 }
4553
4554 assert_ip_generic!(Invariant, usize, bool, char);
4555 }
4556
4557 #[test]
4558 fn struct_with_ip_version_extension_parameter() {
4559 trait FakeIpExt: Ip {
4560 type Associated;
4561 }
4562 impl FakeIpExt for Ipv4 {
4563 type Associated = u8;
4564 }
4565 impl FakeIpExt for Ipv6 {
4566 type Associated = u16;
4567 }
4568
4569 #[allow(dead_code)]
4570 #[derive(GenericOverIp)]
4571 #[generic_over_ip(I, Ip)]
4572 struct Generic<I: FakeIpExt> {
4573 field: I::Associated,
4574 }
4575
4576 assert_ip_generic!(Generic, Ip);
4577 }
4578
4579 #[test]
4580 fn struct_with_ip_version_extension_parameter_but_no_ip_bound() {
4581 trait FakeIpExt: Ip {
4582 type Associated;
4583 }
4584 impl FakeIpExt for Ipv4 {
4585 type Associated = u8;
4586 }
4587 impl FakeIpExt for Ipv6 {
4588 type Associated = u16;
4589 }
4590
4591 #[allow(dead_code)]
4592 #[derive(GenericOverIp)]
4593 #[generic_over_ip(I, Ip)]
4594 struct Generic<I: FakeIpExt> {
4595 field: I::Associated,
4596 }
4597
4598 assert_ip_generic!(Generic, Ip);
4599 }
4600
4601 #[test]
4602 fn struct_with_ip_address_extension_parameter() {
4603 trait FakeIpAddressExt: IpAddress {
4604 type Associated;
4605 }
4606 impl FakeIpAddressExt for Ipv4Addr {
4607 type Associated = u8;
4608 }
4609 impl FakeIpAddressExt for Ipv6Addr {
4610 type Associated = u16;
4611 }
4612
4613 #[allow(dead_code)]
4614 #[derive(GenericOverIp)]
4615 #[generic_over_ip(A, IpAddress)]
4616 struct Generic<A: IpAddress + FakeIpAddressExt> {
4617 field: A::Associated,
4618 }
4619
4620 assert_ip_generic!(Generic, IpAddress);
4621 }
4622
4623 #[test]
4624 fn type_with_lifetime_and_ip_parameter() {
4625 #[allow(dead_code)]
4626 #[derive(GenericOverIp)]
4627 #[generic_over_ip(I, Ip)]
4628 struct Generic<'a, I: Ip> {
4629 field: &'a I::Addr,
4630 }
4631
4632 assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv4, Generic<'static, Ipv4>>();
4633 assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv6, Generic<'static, Ipv6>>();
4634 assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv4, Generic<'static, Ipv4>>();
4635 assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv6, Generic<'static, Ipv6>>();
4636 }
4637
4638 #[test]
4639 fn type_with_lifetime_and_no_ip_parameter() {
4640 #[allow(dead_code)]
4641 #[derive(GenericOverIp)]
4642 #[generic_over_ip()]
4643 struct Generic<'a> {
4644 field: &'a (),
4645 }
4646
4647 assert_ip_generic_is::<Generic<'static>, Ipv4, Generic<'static>>();
4648 assert_ip_generic_is::<Generic<'static>, Ipv6, Generic<'static>>();
4649 }
4650
4651 #[test]
4652 fn type_with_params_list_with_trailing_comma() {
4653 trait IpExtensionTraitWithVeryLongName {}
4654 trait OtherIpExtensionTraitWithVeryLongName {}
4655 trait LongNameToForceFormatterToBreakLineAndAddTrailingComma {}
4656 #[allow(dead_code)]
4658 #[derive(GenericOverIp)]
4659 #[generic_over_ip(I, Ip)]
4660 struct Generic<
4661 I: Ip
4662 + IpExtensionTraitWithVeryLongName
4663 + OtherIpExtensionTraitWithVeryLongName
4664 + LongNameToForceFormatterToBreakLineAndAddTrailingComma,
4665 > {
4666 field: I::Addr,
4667 }
4668 }
4669}