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, NonMulticastAddr, Scope, ScopeableAddress, SpecifiedAddr, SpecifiedAddress,
72 UnicastAddr, 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#[allow(missing_docs)]
1873#[derive(Copy, Clone, Eq, PartialEq)]
1874pub enum Ipv4SourceAddr {
1875 Specified(NonMulticastAddr<SpecifiedAddr<Ipv4Addr>>),
1876 Unspecified,
1877}
1878
1879impl crate::sealed::Sealed for Ipv4SourceAddr {}
1880
1881impl Ipv4SourceAddr {
1882 #[inline]
1887 pub fn new(addr: Ipv4Addr) -> Option<Ipv4SourceAddr> {
1888 match SpecifiedAddr::new(addr) {
1889 Some(addr) => NonMulticastAddr::new(addr).map(Ipv4SourceAddr::Specified),
1890 None => Some(Ipv4SourceAddr::Unspecified),
1891 }
1892 }
1893}
1894
1895impl Witness<Ipv4Addr> for Ipv4SourceAddr {
1896 #[inline]
1897 fn new(addr: Ipv4Addr) -> Option<Ipv4SourceAddr> {
1898 Ipv4SourceAddr::new(addr)
1899 }
1900
1901 #[inline]
1902 unsafe fn new_unchecked(addr: Ipv4Addr) -> Ipv4SourceAddr {
1903 Ipv4SourceAddr::new(addr).unwrap()
1904 }
1905
1906 #[inline]
1907 fn into_addr(self) -> Ipv4Addr {
1908 match self {
1909 Ipv4SourceAddr::Specified(addr) => **addr,
1910 Ipv4SourceAddr::Unspecified => Ipv4::UNSPECIFIED_ADDRESS,
1911 }
1912 }
1913}
1914
1915impl From<Ipv4SourceAddr> for Ipv4Addr {
1916 fn from(addr: Ipv4SourceAddr) -> Ipv4Addr {
1917 addr.get()
1918 }
1919}
1920
1921impl AsRef<Ipv4Addr> for Ipv4SourceAddr {
1922 fn as_ref(&self) -> &Ipv4Addr {
1923 match self {
1924 Ipv4SourceAddr::Specified(addr) => addr,
1925 Ipv4SourceAddr::Unspecified => &Ipv4::UNSPECIFIED_ADDRESS,
1926 }
1927 }
1928}
1929
1930impl Deref for Ipv4SourceAddr {
1931 type Target = Ipv4Addr;
1932
1933 fn deref(&self) -> &Ipv4Addr {
1934 self.as_ref()
1935 }
1936}
1937
1938impl Display for Ipv4SourceAddr {
1939 #[inline]
1940 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1941 write!(f, "{}", self.get())
1942 }
1943}
1944
1945impl Debug for Ipv4SourceAddr {
1946 #[inline]
1947 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1948 Display::fmt(self, f)
1949 }
1950}
1951
1952#[derive(
1987 Copy,
1988 Clone,
1989 Default,
1990 PartialEq,
1991 Eq,
1992 PartialOrd,
1993 Ord,
1994 Hash,
1995 KnownLayout,
1996 FromBytes,
1997 IntoBytes,
1998 Immutable,
1999 Unaligned,
2000)]
2001#[repr(transparent)]
2002pub struct Ipv6Addr([u8; 16]);
2003
2004impl Ipv6Addr {
2005 #[inline]
2007 pub const fn new(segments: [u16; 8]) -> Ipv6Addr {
2008 #![allow(clippy::many_single_char_names)]
2009 let [a, b, c, d, e, f, g, h] = segments;
2010 let [aa, ab] = a.to_be_bytes();
2011 let [ba, bb] = b.to_be_bytes();
2012 let [ca, cb] = c.to_be_bytes();
2013 let [da, db] = d.to_be_bytes();
2014 let [ea, eb] = e.to_be_bytes();
2015 let [fa, fb] = f.to_be_bytes();
2016 let [ga, gb] = g.to_be_bytes();
2017 let [ha, hb] = h.to_be_bytes();
2018 Ipv6Addr([aa, ab, ba, bb, ca, cb, da, db, ea, eb, fa, fb, ga, gb, ha, hb])
2019 }
2020
2021 #[inline]
2023 pub const fn from_bytes(bytes: [u8; 16]) -> Ipv6Addr {
2024 Ipv6Addr(bytes)
2025 }
2026
2027 #[inline]
2029 pub const fn ipv6_bytes(&self) -> [u8; 16] {
2030 self.0
2031 }
2032
2033 #[inline]
2035 pub fn segments(&self) -> [u16; 8] {
2036 #![allow(clippy::many_single_char_names)]
2037 let [a, b, c, d, e, f, g, h]: [zerocopy::network_endian::U16; 8] =
2038 zerocopy::transmute!(self.ipv6_bytes());
2039 [a.into(), b.into(), c.into(), d.into(), e.into(), f.into(), g.into(), h.into()]
2040 }
2041
2042 #[inline]
2047 pub const fn to_solicited_node_address(&self) -> MulticastAddr<Ipv6Addr> {
2048 unsafe {
2056 MulticastAddr::new_unchecked(Ipv6Addr::from_bytes([
2057 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xff, self.0[13], self.0[14],
2058 self.0[15],
2059 ]))
2060 }
2061 }
2062
2063 #[inline]
2070 pub fn is_valid_unicast(&self) -> bool {
2071 !(self.is_loopback() || !self.is_specified() || self.is_multicast())
2072 }
2073
2074 #[inline]
2081 pub fn is_site_local(&self) -> bool {
2082 Ipv6::SITE_LOCAL_UNICAST_SUBNET.contains(self)
2083 }
2084
2085 #[inline]
2090 pub fn is_unicast_link_local(&self) -> bool {
2091 self.is_unicast_in_subnet(&Ipv6::LINK_LOCAL_UNICAST_SUBNET)
2092 }
2093
2094 pub fn to_ipv4_compatible(&self) -> Option<Ipv4Addr> {
2124 if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] = self.0 {
2125 Some(Ipv4Addr::new([a, b, c, d]))
2126 } else {
2127 None
2128 }
2129 }
2130
2131 pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
2151 if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] = self.0 {
2152 Some(Ipv4Addr::new([a, b, c, d]))
2153 } else {
2154 None
2155 }
2156 }
2157}
2158
2159impl sealed::Sealed for Ipv6Addr {}
2160
2161impl From<Ipv4Addr> for Ipv6Addr {
2164 fn from(addr: Ipv4Addr) -> Ipv6Addr {
2165 *addr.to_ipv6_mapped()
2166 }
2167}
2168
2169impl IpAddress for Ipv6Addr {
2170 const BYTES: u8 = 16;
2171
2172 type Version = Ipv6;
2173
2174 #[inline]
2175 fn mask(&self, bits: u8) -> Ipv6Addr {
2176 assert!(bits <= 128);
2177 let mask = u128::MAX.checked_shl((128 - bits).into()).unwrap_or(0);
2181 Ipv6Addr((u128::from_be_bytes(self.0) & mask).to_be_bytes())
2182 }
2183
2184 #[inline]
2185 fn bytes(&self) -> &[u8] {
2186 &self.0
2187 }
2188
2189 #[inline]
2190 fn to_ip_addr(&self) -> IpAddr {
2191 IpAddr::V6(*self)
2192 }
2193
2194 #[inline]
2195 fn common_prefix_len(&self, other: &Ipv6Addr) -> u8 {
2196 let me = u128::from_be_bytes(self.0);
2197 let other = u128::from_be_bytes(other.0);
2198 let same_bits = me ^ other;
2201 same_bits.leading_zeros() as u8
2202 }
2203
2204 #[inline]
2205 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool {
2206 !self.is_multicast() && self.is_specified() && subnet.contains(self)
2207 }
2208
2209 fn subnet_into_either(subnet: Subnet<Ipv6Addr>) -> SubnetEither {
2210 SubnetEither::V6(subnet)
2211 }
2212
2213 #[inline]
2214 fn array_into_ip_addr<const N: usize>(
2215 addrs: [Self; N],
2216 ) -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
2217 IpAddr::V6(addrs)
2218 }
2219}
2220
2221impl UnicastAddress for Ipv6Addr {
2222 #[inline]
2227 fn is_unicast(&self) -> bool {
2228 !self.is_multicast() && self.is_specified()
2229 }
2230}
2231
2232impl From<[u8; 16]> for Ipv6Addr {
2233 #[inline]
2234 fn from(bytes: [u8; 16]) -> Ipv6Addr {
2235 Ipv6Addr::from_bytes(bytes)
2236 }
2237}
2238
2239#[cfg(feature = "std")]
2240impl From<net::Ipv6Addr> for Ipv6Addr {
2241 #[inline]
2242 fn from(addr: net::Ipv6Addr) -> Ipv6Addr {
2243 Ipv6Addr::from_bytes(addr.octets())
2244 }
2245}
2246
2247#[cfg(feature = "std")]
2248impl From<Ipv6Addr> for net::Ipv6Addr {
2249 #[inline]
2250 fn from(addr: Ipv6Addr) -> net::Ipv6Addr {
2251 net::Ipv6Addr::from(addr.ipv6_bytes())
2252 }
2253}
2254
2255impl Display for Ipv6Addr {
2256 #[inline]
2265 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2266 fn fmt_inner<W: fmt::Write>(addr: &Ipv6Addr, w: &mut W) -> Result<(), fmt::Error> {
2271 if !addr.is_specified() {
2275 write!(w, "::")
2276 } else if addr.is_loopback() {
2277 write!(w, "::1")
2278 } else if let Some(v4) = addr.to_ipv4_mapped() {
2279 write!(w, "::ffff:{}", v4)
2280 } else {
2281 let segments = addr.segments();
2282
2283 let longest_zero_span = {
2284 let mut longest_zero_span = 0..0;
2285 let mut current_zero_span = 0..0;
2286 for (i, seg) in segments.iter().enumerate() {
2287 if *seg == 0 {
2288 current_zero_span.end = i + 1;
2289 if current_zero_span.len() > longest_zero_span.len() {
2290 longest_zero_span = current_zero_span.clone();
2291 }
2292 } else {
2293 let next_idx = i + 1;
2294 current_zero_span = next_idx..next_idx;
2295 }
2296 }
2297 longest_zero_span
2298 };
2299
2300 let write_slice = |w: &mut W, slice: &[u16]| {
2301 if let [head, tail @ ..] = slice {
2302 write!(w, "{:x}", head)?;
2303 for seg in tail {
2304 write!(w, ":{:x}", seg)?;
2305 }
2306 }
2307 Ok(())
2308 };
2309
2310 if longest_zero_span.len() > 1 {
2327 write_slice(w, &segments[..longest_zero_span.start])?;
2328 w.write_str("::")?;
2329 write_slice(w, &segments[longest_zero_span.end..])
2330 } else {
2331 write_slice(w, &segments)
2332 }
2333 }
2334 }
2335
2336 if f.precision().is_none() && f.width().is_none() {
2337 fmt_inner(self, f)
2340 } else {
2341 struct ByteSlice<'a>(&'a mut [u8]);
2348
2349 impl<'a> fmt::Write for ByteSlice<'a> {
2350 fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
2351 let from = s.as_bytes();
2352
2353 if from.len() > self.0.len() {
2354 return Err(fmt::Error);
2355 }
2356
2357 let to = mem::replace(&mut self.0, &mut [][..]);
2363 let (to, remaining) = to.split_at_mut(from.len());
2364 to.copy_from_slice(from);
2365
2366 self.0 = remaining;
2367 Ok(())
2368 }
2369 }
2370
2371 const MAX_DISPLAY_LEN: usize = (4 * 8) + 7;
2375 let mut scratch = [0u8; MAX_DISPLAY_LEN];
2376 let mut scratch_slice = ByteSlice(&mut scratch[..]);
2377 fmt_inner(self, &mut scratch_slice)
2384 .expect("<Ipv6Addr as Display>::fmt: fmt_inner should have succeeded because the scratch buffer was long enough");
2385 let unwritten = scratch_slice.0.len();
2386 let len = MAX_DISPLAY_LEN - unwritten;
2387 let str = core::str::from_utf8(&scratch[..len])
2389 .expect("<Ipv6Addr as Display>::fmt: scratch buffer should contain valid UTF-8");
2390 f.pad(str)
2391 }
2392 }
2393}
2394
2395impl Debug for Ipv6Addr {
2396 #[inline]
2397 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2398 Display::fmt(self, f)
2399 }
2400}
2401
2402#[allow(missing_docs)]
2409#[derive(Copy, Clone, Eq, PartialEq)]
2410pub enum Ipv6SourceAddr {
2411 Unicast(NonMappedAddr<UnicastAddr<Ipv6Addr>>),
2412 Unspecified,
2413}
2414
2415impl crate::sealed::Sealed for Ipv6SourceAddr {}
2416
2417impl Ipv6SourceAddr {
2418 #[inline]
2423 pub fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2424 if let Some(addr) = UnicastAddr::new(addr) {
2425 NonMappedAddr::new(addr).map(Ipv6SourceAddr::Unicast)
2426 } else if !addr.is_specified() {
2427 Some(Ipv6SourceAddr::Unspecified)
2428 } else {
2429 None
2430 }
2431 }
2432}
2433
2434impl Witness<Ipv6Addr> for Ipv6SourceAddr {
2435 #[inline]
2436 fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2437 Ipv6SourceAddr::new(addr)
2438 }
2439
2440 #[inline]
2441 unsafe fn new_unchecked(addr: Ipv6Addr) -> Ipv6SourceAddr {
2442 Ipv6SourceAddr::new(addr).unwrap()
2443 }
2444
2445 #[inline]
2446 fn into_addr(self) -> Ipv6Addr {
2447 match self {
2448 Ipv6SourceAddr::Unicast(addr) => **addr,
2449 Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2450 }
2451 }
2452}
2453
2454impl SpecifiedAddress for Ipv6SourceAddr {
2455 fn is_specified(&self) -> bool {
2456 self != &Ipv6SourceAddr::Unspecified
2457 }
2458}
2459
2460impl UnicastAddress for Ipv6SourceAddr {
2461 fn is_unicast(&self) -> bool {
2462 matches!(self, Ipv6SourceAddr::Unicast(_))
2463 }
2464}
2465
2466impl LinkLocalAddress for Ipv6SourceAddr {
2467 fn is_link_local(&self) -> bool {
2468 let addr: Ipv6Addr = self.into();
2469 addr.is_link_local()
2470 }
2471}
2472
2473impl MappedAddress for Ipv6SourceAddr {
2474 fn is_non_mapped(&self) -> bool {
2475 let addr: Ipv6Addr = self.into();
2476 addr.is_non_mapped()
2477 }
2478}
2479
2480impl From<Ipv6SourceAddr> for Ipv6Addr {
2481 fn from(addr: Ipv6SourceAddr) -> Ipv6Addr {
2482 addr.get()
2483 }
2484}
2485
2486impl From<&'_ Ipv6SourceAddr> for Ipv6Addr {
2487 fn from(addr: &Ipv6SourceAddr) -> Ipv6Addr {
2488 match addr {
2489 Ipv6SourceAddr::Unicast(addr) => addr.get(),
2490 Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2491 }
2492 }
2493}
2494
2495impl TryFrom<Ipv6Addr> for Ipv6SourceAddr {
2496 type Error = ();
2497 fn try_from(addr: Ipv6Addr) -> Result<Ipv6SourceAddr, ()> {
2498 Ipv6SourceAddr::new(addr).ok_or(())
2499 }
2500}
2501
2502impl AsRef<Ipv6Addr> for Ipv6SourceAddr {
2503 fn as_ref(&self) -> &Ipv6Addr {
2504 match self {
2505 Ipv6SourceAddr::Unicast(addr) => addr,
2506 Ipv6SourceAddr::Unspecified => &Ipv6::UNSPECIFIED_ADDRESS,
2507 }
2508 }
2509}
2510
2511impl Deref for Ipv6SourceAddr {
2512 type Target = Ipv6Addr;
2513
2514 fn deref(&self) -> &Ipv6Addr {
2515 self.as_ref()
2516 }
2517}
2518
2519impl Display for Ipv6SourceAddr {
2520 #[inline]
2521 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2522 match self {
2523 Ipv6SourceAddr::Unicast(addr) => write!(f, "{}", addr),
2524 Ipv6SourceAddr::Unspecified => write!(f, "::"),
2525 }
2526 }
2527}
2528
2529impl Debug for Ipv6SourceAddr {
2530 #[inline]
2531 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2532 Display::fmt(self, f)
2533 }
2534}
2535
2536#[allow(missing_docs)]
2544#[derive(Copy, Clone, Eq, PartialEq)]
2545pub enum UnicastOrMulticastIpv6Addr {
2546 Unicast(UnicastAddr<Ipv6Addr>),
2547 Multicast(MulticastAddr<Ipv6Addr>),
2548}
2549
2550impl UnicastOrMulticastIpv6Addr {
2551 pub fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2555 SpecifiedAddr::new(addr).map(UnicastOrMulticastIpv6Addr::from_specified)
2556 }
2557
2558 pub fn from_specified(addr: SpecifiedAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2560 if addr.is_unicast() {
2561 UnicastOrMulticastIpv6Addr::Unicast(UnicastAddr(addr.get()))
2562 } else {
2563 UnicastOrMulticastIpv6Addr::Multicast(MulticastAddr(addr.get()))
2564 }
2565 }
2566}
2567
2568impl crate::sealed::Sealed for UnicastOrMulticastIpv6Addr {}
2569
2570impl Witness<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2571 #[inline]
2572 fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2573 UnicastOrMulticastIpv6Addr::new(addr)
2574 }
2575
2576 #[inline]
2577 unsafe fn new_unchecked(addr: Ipv6Addr) -> UnicastOrMulticastIpv6Addr {
2578 UnicastOrMulticastIpv6Addr::new(addr).unwrap()
2579 }
2580
2581 #[inline]
2582 fn into_addr(self) -> Ipv6Addr {
2583 match self {
2584 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.get(),
2585 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.get(),
2586 }
2587 }
2588}
2589
2590impl UnicastAddress for UnicastOrMulticastIpv6Addr {
2591 fn is_unicast(&self) -> bool {
2592 matches!(self, UnicastOrMulticastIpv6Addr::Unicast(_))
2593 }
2594}
2595
2596impl MulticastAddress for UnicastOrMulticastIpv6Addr {
2597 fn is_multicast(&self) -> bool {
2598 matches!(self, UnicastOrMulticastIpv6Addr::Multicast(_))
2599 }
2600}
2601
2602impl LinkLocalAddress for UnicastOrMulticastIpv6Addr {
2603 fn is_link_local(&self) -> bool {
2604 match self {
2605 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_link_local(),
2606 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_link_local(),
2607 }
2608 }
2609}
2610
2611impl MappedAddress for UnicastOrMulticastIpv6Addr {
2612 fn is_non_mapped(&self) -> bool {
2613 match self {
2614 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_non_mapped(),
2615 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_non_mapped(),
2616 }
2617 }
2618}
2619
2620impl From<UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2621 fn from(addr: UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2622 addr.get()
2623 }
2624}
2625
2626impl From<&'_ UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2627 fn from(addr: &UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2628 addr.get()
2629 }
2630}
2631
2632impl From<UnicastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2633 fn from(addr: UnicastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2634 UnicastOrMulticastIpv6Addr::Unicast(addr)
2635 }
2636}
2637
2638impl From<MulticastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2639 fn from(addr: MulticastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2640 UnicastOrMulticastIpv6Addr::Multicast(addr)
2641 }
2642}
2643
2644impl TryFrom<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2645 type Error = ();
2646 fn try_from(addr: Ipv6Addr) -> Result<UnicastOrMulticastIpv6Addr, ()> {
2647 UnicastOrMulticastIpv6Addr::new(addr).ok_or(())
2648 }
2649}
2650
2651impl AsRef<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2652 fn as_ref(&self) -> &Ipv6Addr {
2653 match self {
2654 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr,
2655 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr,
2656 }
2657 }
2658}
2659
2660impl Deref for UnicastOrMulticastIpv6Addr {
2661 type Target = Ipv6Addr;
2662
2663 fn deref(&self) -> &Ipv6Addr {
2664 self.as_ref()
2665 }
2666}
2667
2668impl Display for UnicastOrMulticastIpv6Addr {
2669 #[inline]
2670 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2671 match self {
2672 UnicastOrMulticastIpv6Addr::Unicast(addr) => write!(f, "{}", addr),
2673 UnicastOrMulticastIpv6Addr::Multicast(addr) => write!(f, "{}", addr),
2674 }
2675 }
2676}
2677
2678impl Debug for UnicastOrMulticastIpv6Addr {
2679 #[inline]
2680 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2681 Display::fmt(self, f)
2682 }
2683}
2684
2685#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2687pub enum SubnetError {
2688 PrefixTooLong,
2691 HostBitsSet,
2694}
2695
2696#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2699pub struct PrefixTooLongError;
2700
2701#[derive(Copy, Clone, Eq, PartialEq, Hash)]
2705pub struct Subnet<A> {
2706 network: A,
2708 prefix: u8,
2709}
2710
2711impl<A: core::cmp::Ord> core::cmp::PartialOrd for Subnet<A> {
2712 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
2713 Some(self.cmp(other))
2714 }
2715}
2716
2717impl<A: core::cmp::Ord> core::cmp::Ord for Subnet<A> {
2719 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
2720 let Self { network, prefix } = self;
2721 let Self { network: other_network, prefix: other_prefix } = other;
2722 match prefix.cmp(other_prefix) {
2723 core::cmp::Ordering::Equal => network.cmp(other_network),
2724 ord => ord,
2725 }
2726 }
2727}
2728
2729impl<A> Subnet<A> {
2730 #[inline]
2740 pub const unsafe fn new_unchecked(network: A, prefix: u8) -> Subnet<A> {
2741 Subnet { network, prefix }
2742 }
2743}
2744
2745impl<A: IpAddress> Subnet<A> {
2746 #[inline]
2753 pub fn new(network: A, prefix: u8) -> Result<Subnet<A>, SubnetError> {
2754 if prefix > A::BYTES * 8 {
2755 return Err(SubnetError::PrefixTooLong);
2756 }
2757 if network != network.mask(prefix) {
2760 return Err(SubnetError::HostBitsSet);
2761 }
2762 Ok(Subnet { network, prefix })
2763 }
2764
2765 #[inline]
2771 pub fn from_host(host: A, prefix: u8) -> Result<Subnet<A>, PrefixTooLongError> {
2772 if prefix > A::BYTES * 8 {
2773 return Err(PrefixTooLongError);
2774 }
2775 let network = host.mask(prefix);
2776 Ok(Subnet { network, prefix })
2777 }
2778
2779 #[inline]
2783 pub fn network(&self) -> A {
2784 self.network
2785 }
2786
2787 #[inline]
2789 pub fn prefix(&self) -> u8 {
2790 self.prefix
2791 }
2792
2793 #[inline]
2799 pub fn contains(&self, addr: &A) -> bool {
2800 self.network == addr.mask(self.prefix)
2801 }
2802}
2803
2804impl Subnet<Ipv4Addr> {
2805 #[inline]
2813 pub fn broadcast(self) -> Ipv4Addr {
2814 if self.prefix == 32 {
2815 self.network
2817 } else {
2818 let mask = <u32>::max_value() >> self.prefix;
2819 Ipv4Addr::new((u32::from_be_bytes(self.network.0) | mask).to_be_bytes())
2820 }
2821 }
2822}
2823
2824impl<A: IpAddress> Display for Subnet<A> {
2825 #[inline]
2826 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2827 write!(f, "{}/{}", self.network, self.prefix)
2828 }
2829}
2830
2831impl<A: IpAddress> Debug for Subnet<A> {
2832 #[inline]
2833 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2834 write!(f, "{}/{}", self.network, self.prefix)
2835 }
2836}
2837
2838impl<A, I: Ip> GenericOverIp<I> for Subnet<A> {
2839 type Type = Subnet<I::Addr>;
2840}
2841
2842#[allow(missing_docs)]
2848#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2849pub enum SubnetEither {
2850 V4(Subnet<Ipv4Addr>),
2851 V6(Subnet<Ipv6Addr>),
2852}
2853
2854impl SubnetEither {
2855 #[inline]
2862 pub fn new(network: IpAddr, prefix: u8) -> Result<SubnetEither, SubnetError> {
2863 Ok(match network {
2864 IpAddr::V4(network) => SubnetEither::V4(Subnet::new(network, prefix)?),
2865 IpAddr::V6(network) => SubnetEither::V6(Subnet::new(network, prefix)?),
2866 })
2867 }
2868
2869 #[inline]
2875 pub fn from_host(host: IpAddr, prefix: u8) -> Result<SubnetEither, PrefixTooLongError> {
2876 Ok(match host {
2877 IpAddr::V4(host) => SubnetEither::V4(Subnet::from_host(host, prefix)?),
2878 IpAddr::V6(host) => SubnetEither::V6(Subnet::from_host(host, prefix)?),
2879 })
2880 }
2881
2882 #[inline]
2884 pub fn net_prefix(&self) -> (IpAddr, u8) {
2885 match self {
2886 SubnetEither::V4(v4) => (v4.network.into(), v4.prefix),
2887 SubnetEither::V6(v6) => (v6.network.into(), v6.prefix),
2888 }
2889 }
2890}
2891
2892impl<A: IpAddress> From<Subnet<A>> for SubnetEither {
2893 fn from(subnet: Subnet<A>) -> SubnetEither {
2894 A::subnet_into_either(subnet)
2895 }
2896}
2897
2898#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2900pub enum AddrSubnetError {
2901 PrefixTooLong,
2904 NotUnicastInSubnet,
2907 InvalidWitness,
2909}
2910
2911#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2922pub struct AddrSubnet<S: IpAddress, A: Witness<S> + Copy = SpecifiedAddr<S>> {
2923 addr: A,
2927 subnet: Subnet<S>,
2928}
2929
2930impl<S: IpAddress, A: Witness<S> + Copy> AddrSubnet<S, A> {
2931 #[inline]
2939 pub fn new(addr: S, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2940 AddrSubnet::from_witness(A::new(addr).ok_or(AddrSubnetError::InvalidWitness)?, prefix)
2941 }
2942
2943 #[inline]
2954 pub unsafe fn new_unchecked(addr: S, prefix: u8) -> Self {
2955 let (subnet, addr) =
2956 unsafe { (Subnet::new_unchecked(addr.mask(prefix), prefix), A::new_unchecked(addr)) };
2957 AddrSubnet { addr, subnet }
2958 }
2959
2960 pub fn from_witness(addr: A, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2969 if prefix > S::BYTES * 8 {
2970 return Err(AddrSubnetError::PrefixTooLong);
2971 }
2972 let subnet = Subnet { network: addr.as_ref().mask(prefix), prefix };
2973 if !addr.as_ref().is_unicast_in_subnet(&subnet) {
2974 return Err(AddrSubnetError::NotUnicastInSubnet);
2975 }
2976 Ok(AddrSubnet { addr, subnet })
2977 }
2978
2979 #[inline]
2981 pub fn subnet(&self) -> Subnet<S> {
2982 self.subnet
2983 }
2984
2985 #[inline]
2987 pub fn addr(&self) -> A {
2988 self.addr
2989 }
2990
2991 #[inline]
2993 pub fn addr_subnet(self) -> (A, Subnet<S>) {
2994 (self.addr, self.subnet)
2995 }
2996
2997 #[inline]
2999 pub fn to_witness<B: Witness<S> + Copy>(&self) -> AddrSubnet<S, B>
3000 where
3001 A: Into<B>,
3002 {
3003 AddrSubnet { addr: self.addr.into(), subnet: self.subnet }
3004 }
3005
3006 #[inline]
3008 pub fn add_witness<B: Witness<A> + Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
3009 let addr = B::new(self.addr)?;
3010 Some(AddrSubnet { addr, subnet: self.subnet })
3011 }
3012
3013 #[inline]
3015 pub fn replace_witness<B: Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
3016 let addr = B::new(self.addr.get())?;
3017 Some(AddrSubnet { addr, subnet: self.subnet })
3018 }
3019}
3020
3021impl<S: IpAddress, A: Witness<S> + Copy + Display> Display for AddrSubnet<S, A> {
3022 #[inline]
3023 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
3024 write!(f, "{}/{}", self.addr, self.subnet.prefix)
3025 }
3026}
3027
3028impl<A: Witness<Ipv6Addr> + Copy> AddrSubnet<Ipv6Addr, A> {
3029 pub fn ipv6_unicast_addr(&self) -> UnicastAddr<Ipv6Addr> {
3035 unsafe { UnicastAddr::new_unchecked(self.addr.get()) }
3036 }
3037
3038 pub fn to_unicast(&self) -> AddrSubnet<Ipv6Addr, UnicastAddr<Ipv6Addr>> {
3044 let AddrSubnet { addr, subnet } = *self;
3045 let addr = unsafe { UnicastAddr::new_unchecked(addr.get()) };
3046 AddrSubnet { addr, subnet }
3047 }
3048}
3049
3050#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, GenericOverIp)]
3052#[generic_over_ip(I, Ip)]
3053pub struct PrefixLength<I: Ip> {
3054 inner: u8,
3056 _ip: IpVersionMarker<I>,
3057}
3058
3059impl<I: Ip> PrefixLength<I> {
3060 pub const fn get(self) -> u8 {
3065 let Self { inner, _ip } = self;
3066 inner
3067 }
3068
3069 pub fn get_mask(self) -> I::Addr {
3071 I::map_ip(
3072 self,
3073 |prefix_len| Ipv4::LIMITED_BROADCAST_ADDRESS.mask(prefix_len.get()),
3074 |prefix_len| Ipv6Addr([u8::MAX; 16]).mask(prefix_len.get()),
3075 )
3076 }
3077
3078 pub const unsafe fn new_unchecked(prefix_length: u8) -> Self {
3085 Self { inner: prefix_length, _ip: I::VERSION_MARKER }
3086 }
3087
3088 pub const fn new(prefix_length: u8) -> Result<Self, PrefixTooLongError> {
3093 if prefix_length > I::Addr::BYTES * 8 {
3094 return Err(PrefixTooLongError);
3095 }
3096 Ok(Self { inner: prefix_length, _ip: I::VERSION_MARKER })
3097 }
3098
3099 pub fn try_from_subnet_mask(subnet_mask: I::Addr) -> Result<Self, NotSubnetMaskError> {
3104 let IpInvariant((count_ones, leading_ones)) = I::map_ip(
3105 subnet_mask,
3106 |subnet_mask| {
3107 let number = u32::from_be_bytes(subnet_mask.ipv4_bytes());
3108 IpInvariant((number.count_ones(), number.leading_ones()))
3109 },
3110 |subnet_mask| {
3111 let number = u128::from_be_bytes(subnet_mask.ipv6_bytes());
3112 IpInvariant((number.count_ones(), number.leading_ones()))
3113 },
3114 );
3115
3116 if leading_ones != count_ones {
3117 return Err(NotSubnetMaskError);
3118 }
3119
3120 Ok(Self {
3121 inner: u8::try_from(leading_ones)
3122 .expect("the number of bits in an IP address fits in u8"),
3123 _ip: IpVersionMarker::default(),
3124 })
3125 }
3126}
3127
3128impl<I: Ip> From<PrefixLength<I>> for u8 {
3129 fn from(value: PrefixLength<I>) -> Self {
3130 value.get()
3131 }
3132}
3133
3134#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3137pub struct NotSubnetMaskError;
3138
3139pub trait IpAddressWitness<A: IpAddress>: Witness<A> {
3152 type IpAddrWitness: IpAddrWitness + From<Self>;
3157}
3158
3159macro_rules! impl_ip_address_witness {
3160 ($witness:ident) => {
3161 impl<A: IpAddress> IpAddressWitness<A> for $witness<A> {
3162 type IpAddrWitness = $witness<IpAddr>;
3163 }
3164 };
3165}
3166
3167impl_ip_address_witness!(SpecifiedAddr);
3168impl_ip_address_witness!(MulticastAddr);
3169impl_ip_address_witness!(LinkLocalAddr);
3170
3171pub trait IpAddrWitness: Witness<IpAddr> + Into<IpAddr<Self::V4, Self::V6>> + Copy {
3185 type V4: Witness<Ipv4Addr> + Into<Self> + Copy;
3190
3191 type V6: Witness<Ipv6Addr> + Into<Self> + Copy;
3196
3197 fn from_v4(addr: Self::V4) -> Self {
3202 addr.into()
3203 }
3204
3205 fn from_v6(addr: Self::V6) -> Self {
3207 addr.into()
3208 }
3209}
3210
3211macro_rules! impl_ip_addr_witness {
3212 ($witness:ident) => {
3213 impl IpAddrWitness for $witness<IpAddr> {
3214 type V4 = $witness<Ipv4Addr>;
3215 type V6 = $witness<Ipv6Addr>;
3216 }
3217 };
3218}
3219
3220impl_ip_addr_witness!(SpecifiedAddr);
3221impl_ip_addr_witness!(MulticastAddr);
3222impl_ip_addr_witness!(LinkLocalAddr);
3223
3224#[allow(missing_docs)]
3231#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
3232pub enum AddrSubnetEither<A: IpAddrWitness = SpecifiedAddr<IpAddr>> {
3233 V4(AddrSubnet<Ipv4Addr, A::V4>),
3234 V6(AddrSubnet<Ipv6Addr, A::V6>),
3235}
3236
3237impl<A: IpAddrWitness> AddrSubnetEither<A> {
3238 #[inline]
3244 pub fn new(addr: IpAddr, prefix: u8) -> Result<AddrSubnetEither<A>, AddrSubnetError> {
3245 Ok(match addr {
3246 IpAddr::V4(addr) => AddrSubnetEither::V4(AddrSubnet::new(addr, prefix)?),
3247 IpAddr::V6(addr) => AddrSubnetEither::V6(AddrSubnet::new(addr, prefix)?),
3248 })
3249 }
3250
3251 #[inline]
3261 pub unsafe fn new_unchecked(addr: IpAddr, prefix: u8) -> Self {
3262 match addr {
3263 IpAddr::V4(addr) => {
3264 AddrSubnetEither::V4(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3265 }
3266 IpAddr::V6(addr) => {
3267 AddrSubnetEither::V6(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3268 }
3269 }
3270 }
3271
3272 pub fn addr(&self) -> A {
3274 match self {
3275 AddrSubnetEither::V4(v4) => v4.addr.into(),
3276 AddrSubnetEither::V6(v6) => v6.addr.into(),
3277 }
3278 }
3279
3280 #[inline]
3282 pub fn addr_prefix(&self) -> (A, u8) {
3283 match self {
3284 AddrSubnetEither::V4(v4) => (v4.addr.into(), v4.subnet.prefix),
3285 AddrSubnetEither::V6(v6) => (v6.addr.into(), v6.subnet.prefix),
3286 }
3287 }
3288
3289 #[inline]
3291 pub fn addr_subnet(&self) -> (A, SubnetEither) {
3292 match self {
3293 AddrSubnetEither::V4(v4) => (v4.addr.into(), SubnetEither::V4(v4.subnet)),
3294 AddrSubnetEither::V6(v6) => (v6.addr.into(), SubnetEither::V6(v6.subnet)),
3295 }
3296 }
3297}
3298
3299impl<S: IpAddress, A: IpAddressWitness<S> + Copy> From<AddrSubnet<S, A>>
3300 for AddrSubnetEither<A::IpAddrWitness>
3301{
3302 #[inline]
3303 fn from(addr_sub: AddrSubnet<S, A>) -> AddrSubnetEither<A::IpAddrWitness> {
3304 let (addr, sub) = addr_sub.addr_subnet();
3305 AddrSubnetEither::new(addr.get().to_ip_addr(), sub.prefix()).unwrap()
3316 }
3317}
3318
3319impl<A> Display for AddrSubnetEither<A>
3320where
3321 A: IpAddrWitness,
3322 A::V4: Display,
3323 A::V6: Display,
3324{
3325 #[inline]
3326 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
3327 match self {
3328 Self::V4(a) => write!(f, "{}", a),
3329 Self::V6(a) => write!(f, "{}", a),
3330 }
3331 }
3332}
3333
3334pub trait GenericOverIp<NewIp: Ip> {
3353 type Type;
3356}
3357
3358pub struct IpInvariant<T>(pub T);
3363
3364impl<T> IpInvariant<T> {
3365 pub fn into_inner(self) -> T {
3367 self.0
3368 }
3369}
3370
3371impl<I: Ip, T> GenericOverIp<I> for IpInvariant<T> {
3372 type Type = Self;
3373}
3374
3375impl<I: Ip> GenericOverIp<I> for core::convert::Infallible {
3376 type Type = Self;
3377}
3378
3379#[derive(GenericOverIp, Default, Debug, PartialOrd, Ord, Eq, PartialEq, Hash)]
3381#[generic_over_ip(I, Ip)]
3382pub struct IpMarked<I: Ip, T> {
3383 inner: T,
3384 _marker: IpVersionMarker<I>,
3385}
3386
3387impl<I: Ip, T> Deref for IpMarked<I, T> {
3388 type Target = T;
3389
3390 fn deref(&self) -> &Self::Target {
3391 self.as_ref()
3392 }
3393}
3394
3395impl<I: Ip, T> DerefMut for IpMarked<I, T> {
3396 fn deref_mut(&mut self) -> &mut Self::Target {
3397 self.as_mut()
3398 }
3399}
3400impl<I: Ip, T> AsRef<T> for IpMarked<I, T> {
3401 fn as_ref(&self) -> &T {
3402 &self.inner
3403 }
3404}
3405
3406impl<I: Ip, T> AsMut<T> for IpMarked<I, T> {
3407 fn as_mut(&mut self) -> &mut T {
3408 &mut self.inner
3409 }
3410}
3411
3412impl<I: Ip, T> IpMarked<I, T> {
3413 pub fn new(inner: T) -> Self {
3415 Self { inner, _marker: IpVersionMarker::<I>::new() }
3416 }
3417
3418 pub fn into_inner(self) -> T {
3420 let Self { inner, _marker } = self;
3421 inner
3422 }
3423
3424 pub fn get(&self) -> &T {
3426 self.as_ref()
3427 }
3428
3429 pub fn get_mut(&mut self) -> &mut T {
3431 self.as_mut()
3432 }
3433}
3434
3435macro_rules! for_each_tuple_ {
3437 ( $m:ident !! ) => ( $m! { });
3438 ( $m:ident !! $h:ident, $($t:ident,)* ) => (
3439 $m! { $h $($t)* }
3440 for_each_tuple_! { $m !! $($t,)* }
3441 );
3442 }
3443
3444macro_rules! for_each_tuple {
3446 ($m:ident) => {
3447 for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, }
3448 };
3449}
3450
3451macro_rules! ip_generic_tuple {
3453 () => {
3454 impl<I: Ip> GenericOverIp<I> for () {
3455 type Type = Self;
3456 }
3457 };
3458 ( $name0:ident $($name:ident)* ) => (
3459 impl<P: Ip, $name0: GenericOverIp<P>, $($name: GenericOverIp<P>,)*>
3460 GenericOverIp<P> for ($name0, $($name,)*) {
3461 type Type = ($name0::Type, $($name::Type,)*);
3462 }
3463 );
3464 }
3465
3466for_each_tuple!(ip_generic_tuple);
3467
3468macro_rules! ip_generic {
3469 ( $type:ident < $($params:ident),* >) => {
3470 impl<IpType: Ip, $($params: GenericOverIp<IpType>),*>
3471 GenericOverIp<IpType> for $type<$($params),*> {
3472 type Type = $type<$($params::Type),*>;
3473 }
3474 };
3475 ( $type:ident) => {
3476 impl<IpType: Ip> GenericOverIp<IpType> for $type {
3477 type Type = Self;
3478 }
3479 }
3480}
3481
3482ip_generic!(bool);
3484ip_generic!(isize);
3485ip_generic!(i8);
3486ip_generic!(i16);
3487ip_generic!(i32);
3488ip_generic!(i64);
3489ip_generic!(usize);
3490ip_generic!(u8);
3491ip_generic!(u16);
3492ip_generic!(u32);
3493ip_generic!(u64);
3494ip_generic!(Option<T>);
3495ip_generic!(Result<R, E>);
3496#[cfg(feature = "std")]
3497ip_generic!(Vec<T>);
3498
3499impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s T
3500where
3501 T::Type: 's,
3502{
3503 type Type = &'s T::Type;
3504}
3505
3506impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s mut T
3507where
3508 T::Type: 's,
3509{
3510 type Type = &'s mut T::Type;
3511}
3512
3513#[cfg(test)]
3514mod tests {
3515 use super::*;
3516 use test_case::test_case;
3517
3518 #[test]
3519 fn test_map_ip_associated_constant() {
3520 fn get_loopback_address<I: Ip>() -> SpecifiedAddr<I::Addr> {
3521 I::map_ip((), |()| Ipv4::LOOPBACK_ADDRESS, |()| Ipv6::LOOPBACK_ADDRESS)
3522 }
3523
3524 assert_eq!(get_loopback_address::<Ipv4>(), Ipv4::LOOPBACK_ADDRESS);
3525 assert_eq!(get_loopback_address::<Ipv6>(), Ipv6::LOOPBACK_ADDRESS);
3526 }
3527
3528 #[test]
3529 fn test_map_ip_different_behavior() {
3530 fn filter_v4<I: Ip>(addr: I::Addr) -> Option<I::Addr> {
3531 I::map_ip(addr, |addr| Some(addr), |_addr| None)
3532 }
3533
3534 assert_eq!(filter_v4::<Ipv4>(*Ipv4::LOOPBACK_ADDRESS), Some(*Ipv4::LOOPBACK_ADDRESS));
3535 assert_eq!(filter_v4::<Ipv6>(*Ipv6::LOOPBACK_ADDRESS), None);
3536 }
3537
3538 #[test]
3539 fn test_map_ip_extension_trait_fn() {
3540 trait FakeIpExt: Ip {
3541 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr;
3542 }
3543
3544 impl FakeIpExt for Ipv4 {
3545 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3546 let Ipv4Addr(mut bytes) = a;
3547 bytes.reverse();
3548 Ipv4Addr(bytes)
3549 }
3550 }
3551 impl FakeIpExt for Ipv6 {
3552 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3553 let Ipv6Addr(mut bytes) = a;
3554 bytes.reverse();
3555 Ipv6Addr(bytes)
3556 }
3557 }
3558
3559 fn reverse_bytes<A: IpAddress>(addr: A) -> A
3560 where
3561 A::Version: FakeIpExt,
3562 {
3563 A::Version::map_ip(addr, Ipv4::reverse_addr_bytes, Ipv6::reverse_addr_bytes)
3564 }
3565
3566 assert_eq!(reverse_bytes(Ipv4Addr([1, 2, 3, 4])), Ipv4Addr([4, 3, 2, 1]));
3567 assert_eq!(
3568 reverse_bytes(Ipv6Addr([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])),
3569 Ipv6Addr([16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
3570 );
3571 }
3572
3573 #[test]
3574 fn test_map_ip_extension_trait_associated_type() {
3575 trait FakeIpExt: Ip {
3576 type PackedInt;
3577 }
3578 impl FakeIpExt for Ipv4 {
3579 type PackedInt = u32;
3580 }
3581 impl FakeIpExt for Ipv6 {
3582 type PackedInt = u128;
3583 }
3584
3585 #[derive(Debug, PartialEq)]
3586 struct Int<T>(T);
3587
3588 impl<T, I: FakeIpExt> GenericOverIp<I> for Int<T> {
3589 type Type = Int<I::PackedInt>;
3590 }
3591
3592 fn from_be_bytes<A: IpAddress>(addr: A) -> Int<<A::Version as FakeIpExt>::PackedInt>
3593 where
3594 A::Version: FakeIpExt,
3595 {
3596 A::Version::map_ip(
3597 addr,
3598 |Ipv4Addr(bytes)| Int(<Ipv4 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3599 |Ipv6Addr(bytes)| Int(<Ipv6 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3600 )
3601 }
3602
3603 assert_eq!(from_be_bytes(Ipv4::LOOPBACK_ADDRESS.get()), Int(0x7f000001u32));
3604 assert_eq!(from_be_bytes(Ipv6::LOOPBACK_ADDRESS.get()), Int(1u128));
3605 }
3606
3607 #[test]
3608 fn map_ip_twice() {
3609 struct FooV4 {
3610 field: Ipv4Addr,
3611 }
3612
3613 impl Default for FooV4 {
3614 fn default() -> Self {
3615 Self { field: Ipv4::UNSPECIFIED_ADDRESS }
3616 }
3617 }
3618
3619 struct FooV6 {
3620 field: Ipv6Addr,
3621 }
3622
3623 impl Default for FooV6 {
3624 fn default() -> Self {
3625 Self { field: Ipv6::UNSPECIFIED_ADDRESS }
3626 }
3627 }
3628
3629 trait IpExt {
3630 type Foo: Default;
3631 }
3632
3633 impl IpExt for Ipv4 {
3634 type Foo = FooV4;
3635 }
3636
3637 impl IpExt for Ipv6 {
3638 type Foo = FooV6;
3639 }
3640
3641 #[derive(GenericOverIp)]
3642 #[generic_over_ip(I, Ip)]
3643 struct Foo<I: IpExt>(I::Foo);
3644
3645 fn do_something<I: Ip + IpExt>(
3646 foo: Foo<I>,
3647 extra_foo: Foo<I>,
3648 captured_foo: Foo<I>,
3649 ) -> I::Addr {
3650 let addr: I::Addr = map_ip_twice!(I, foo, |Foo(foo)| { foo.field });
3651
3652 let _: I::Addr =
3655 map_ip_twice!(<<I as Ip>::Addr as IpAddress>::Version, extra_foo, |Foo(foo)| {
3656 let _: &Foo<I> = &captured_foo;
3660 foo.field
3661 });
3662
3663 addr
3664 }
3665
3666 assert_eq!(
3667 do_something(
3668 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3669 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3670 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS })
3671 ),
3672 Ipv4::UNSPECIFIED_ADDRESS
3673 );
3674 assert_eq!(
3675 do_something(
3676 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3677 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3678 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS })
3679 ),
3680 Ipv6::UNSPECIFIED_ADDRESS
3681 );
3682
3683 fn do_something_with_default_type_alias_shadowing<I: Ip>() -> (I::Addr, IpVersion) {
3684 let (field, IpInvariant(version)) = map_ip_twice!(I, (), |()| {
3685 let foo: Foo<I> = Foo(<I as IpExt>::Foo::default());
3688 (foo.0.field, IpInvariant(I::VERSION))
3689 },);
3690 (field, version)
3691 }
3692
3693 fn do_something_with_type_alias<I: Ip>() -> (I::Addr, IpVersion) {
3694 #[allow(dead_code)]
3697 type IpAlias = usize;
3698
3699 let (field, IpInvariant(version)) = map_ip_twice!(I as IpAlias, (), |()| {
3700 let foo: Foo<IpAlias> = Foo(<IpAlias as IpExt>::Foo::default());
3704 (foo.0.field, IpInvariant(IpAlias::VERSION))
3705 },);
3706 (field, version)
3707 }
3708
3709 assert_eq!(
3710 do_something_with_default_type_alias_shadowing::<Ipv4>(),
3711 (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3712 );
3713 assert_eq!(
3714 do_something_with_default_type_alias_shadowing::<Ipv6>(),
3715 (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3716 );
3717 assert_eq!(
3718 do_something_with_type_alias::<Ipv4>(),
3719 (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3720 );
3721 assert_eq!(
3722 do_something_with_type_alias::<Ipv6>(),
3723 (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3724 );
3725 }
3726
3727 #[test]
3728 fn test_loopback_unicast() {
3729 assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
3733 assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
3734 }
3735
3736 #[test]
3737 fn test_specified() {
3738 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_specified());
3745 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_specified());
3746
3747 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_unicast());
3750
3751 let unicast = Ipv6Addr([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
3752 assert!(unicast.is_unicast());
3753 assert!(unicast.is_specified());
3754
3755 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_multicast());
3758 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_multicast());
3759
3760 let multicast = Ipv4::MULTICAST_SUBNET.network;
3761 assert!(multicast.is_multicast());
3762 assert!(multicast.is_specified());
3763 let multicast = Ipv6::MULTICAST_SUBNET.network;
3764 assert!(multicast.is_multicast());
3765 assert!(multicast.is_specified());
3766
3767 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_link_local());
3770 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_link_local());
3771
3772 let link_local = Ipv4::LINK_LOCAL_UNICAST_SUBNET.network;
3773 assert!(link_local.is_link_local());
3774 assert!(link_local.is_specified());
3775 let link_local = Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network;
3776 assert!(link_local.is_link_local());
3777 assert!(link_local.is_specified());
3778 let link_local = Ipv6::LINK_LOCAL_UNICAST_SUBNET.network;
3779 assert!(link_local.is_link_local());
3780 assert!(link_local.is_specified());
3781 let mut link_local = Ipv6::MULTICAST_SUBNET.network;
3782 link_local.0[1] = 0x02;
3783 assert!(link_local.is_link_local());
3784 assert!(link_local.is_specified());
3785 assert!(Ipv6::LOOPBACK_ADDRESS.is_link_local());
3786 }
3787
3788 #[test]
3789 fn test_link_local() {
3790 assert!(Ipv4::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3792 assert!(Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network.is_link_local());
3793
3794 assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3796 assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_unicast_link_local());
3797 let mut addr = Ipv6::MULTICAST_SUBNET.network;
3798 for flags in 0..=0x0F {
3799 addr.0[1] = (flags << 4) | 0x02;
3801 assert!(addr.is_link_local());
3804 assert!(!addr.is_unicast_link_local());
3805 }
3806
3807 let mut addr = Ipv6::LOOPBACK_ADDRESS.get();
3811 addr.0[1] = 0x02;
3813 assert!(!addr.is_link_local());
3814 }
3815
3816 #[test]
3817 fn test_subnet_new() {
3818 assert_eq!(
3819 Subnet::new(Ipv4Addr::new([255, 255, 255, 255]), 32).unwrap(),
3820 Subnet { network: Ipv4Addr::new([255, 255, 255, 255]), prefix: 32 },
3821 );
3822 assert_eq!(
3824 Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 33),
3825 Err(SubnetError::PrefixTooLong)
3826 );
3827 assert_eq!(
3828 Subnet::from_host(Ipv4Addr::new([255, 255, 255, 255]), 33),
3829 Err(PrefixTooLongError)
3830 );
3831 assert_eq!(Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 8), Err(SubnetError::HostBitsSet));
3833 assert_eq!(
3835 Subnet::from_host(Ipv4Addr::new([255, 255, 0, 0]), 8),
3836 Ok(Subnet { network: Ipv4Addr::new([255, 0, 0, 0]), prefix: 8 })
3837 );
3838
3839 assert_eq!(
3840 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32).unwrap(),
3841 AddrSubnet {
3842 addr: SpecifiedAddr(Ipv4Addr::new([1, 2, 3, 4])),
3843 subnet: Subnet { network: Ipv4Addr::new([1, 2, 3, 4]), prefix: 32 }
3844 }
3845 );
3846 assert!(
3850 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::UNSPECIFIED_ADDRESS, 16)
3851 == Err(AddrSubnetError::InvalidWitness)
3852 );
3853 assert!(
3854 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv6::UNSPECIFIED_ADDRESS, 64)
3855 == Err(AddrSubnetError::InvalidWitness)
3856 );
3857 assert!(
3859 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 33)
3860 == Err(AddrSubnetError::PrefixTooLong)
3861 );
3862 assert!(
3863 AddrSubnet::<_, SpecifiedAddr<_>>::new(
3864 Ipv6Addr::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
3865 129,
3866 ) == Err(AddrSubnetError::PrefixTooLong)
3867 );
3868 assert!(
3870 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::LIMITED_BROADCAST_ADDRESS.get(), 16)
3871 == Err(AddrSubnetError::NotUnicastInSubnet)
3872 );
3873 assert!(
3875 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([192, 168, 255, 255]), 16)
3876 == Err(AddrSubnetError::NotUnicastInSubnet)
3877 );
3878 assert!(
3880 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([224, 0, 0, 1]), 16)
3881 == Err(AddrSubnetError::NotUnicastInSubnet)
3882 );
3883 assert!(
3884 AddrSubnet::<_, SpecifiedAddr<_>>::new(
3885 Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
3886 64,
3887 ) == Err(AddrSubnetError::NotUnicastInSubnet)
3888 );
3889
3890 assert!(
3894 AddrSubnet::<_, LinkLocalAddr<Ipv4Addr>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32)
3895 == Err(AddrSubnetError::InvalidWitness)
3896 );
3897 }
3898
3899 #[test]
3900 fn test_is_unicast_in_subnet() {
3901 let subnet =
3903 Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).expect("1.2.0.0/16 is a valid subnet");
3904 assert!(Ipv4Addr::new([1, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3905 assert!(!Ipv4Addr::new([2, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3906
3907 let subnet =
3908 Subnet::new(Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 64)
3909 .expect("1::/64 is a valid subnet");
3910 assert!(Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3911 .is_unicast_in_subnet(&subnet));
3912 assert!(!Ipv6Addr::from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3913 .is_unicast_in_subnet(&subnet));
3914
3915 assert!(!Ipv4::UNSPECIFIED_ADDRESS
3917 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 16).unwrap()));
3918 assert!(!Ipv6::UNSPECIFIED_ADDRESS
3919 .is_unicast_in_subnet(&Subnet::new(Ipv6::UNSPECIFIED_ADDRESS, 64).unwrap()));
3920 assert!(!Ipv4::UNSPECIFIED_ADDRESS
3923 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 31).unwrap()));
3924 assert!(!Ipv4::UNSPECIFIED_ADDRESS
3925 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 32).unwrap()));
3926 assert!(!Ipv4Addr::new([1, 2, 0, 0])
3928 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap()));
3929 assert!(Ipv4Addr::new([1, 2, 3, 0])
3931 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 31).unwrap()));
3932 assert!(Ipv4Addr::new([1, 2, 3, 0])
3933 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 32).unwrap()));
3934 assert!(!Ipv4::LIMITED_BROADCAST_ADDRESS
3936 .get()
3937 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([128, 0, 0, 0]), 1).unwrap()));
3938 assert!(!Ipv4Addr::new([1, 2, 255, 255])
3940 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap()));
3941 assert!(Ipv4Addr::new([1, 2, 255, 255])
3943 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 254]), 31).unwrap()));
3944 assert!(Ipv4Addr::new([1, 2, 255, 255])
3945 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 255]), 32).unwrap()));
3946 assert!(!Ipv4Addr::new([224, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::MULTICAST_SUBNET));
3948 assert!(!Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3949 .is_unicast_in_subnet(&Ipv6::MULTICAST_SUBNET));
3950 assert!(!Ipv4Addr::new([240, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::CLASS_E_SUBNET));
3952 }
3953
3954 macro_rules! add_mask_test {
3955 ($name:ident, $addr:ident, $from_ip:expr => {
3956 $($mask:expr => $to_ip:expr),*
3957 }) => {
3958 #[test]
3959 fn $name() {
3960 let from = $addr::from($from_ip);
3961 $(assert_eq!(from.mask($mask), $addr::from($to_ip), "(`{}`.mask({}))", from, $mask);)*
3962 }
3963 };
3964 ($name:ident, $addr:ident, $from_ip:expr => {
3965 $($mask:expr => $to_ip:expr),*,
3966 }) => {
3967 add_mask_test!($name, $addr, $from_ip => { $($mask => $to_ip),* });
3968 };
3969 }
3970
3971 add_mask_test!(v4_full_mask, Ipv4Addr, [255, 254, 253, 252] => {
3972 32 => [255, 254, 253, 252],
3973 28 => [255, 254, 253, 240],
3974 24 => [255, 254, 253, 0],
3975 20 => [255, 254, 240, 0],
3976 16 => [255, 254, 0, 0],
3977 12 => [255, 240, 0, 0],
3978 8 => [255, 0, 0, 0],
3979 4 => [240, 0, 0, 0],
3980 0 => [0, 0, 0, 0],
3981 });
3982
3983 add_mask_test!(v6_full_mask, Ipv6Addr,
3984 [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0] => {
3985 128 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0],
3986 112 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0x00, 0x00],
3987 96 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0x00, 0x00, 0x00, 0x00],
3988 80 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3989 64 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3990 48 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3991 32 => [0xFF, 0xFE, 0xFD, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3992 16 => [0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3993 8 => [0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3994 0 => [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3995 }
3996 );
3997
3998 #[test_case([255, 255, 255, 0] => Ok(24))]
3999 #[test_case([255, 255, 254, 0] => Ok(23))]
4000 #[test_case([255, 255, 253, 0] => Err(NotSubnetMaskError))]
4001 #[test_case([255, 255, 0, 255] => Err(NotSubnetMaskError))]
4002 #[test_case([255, 255, 255, 255] => Ok(32))]
4003 #[test_case([0, 0, 0, 0] => Ok(0))]
4004 #[test_case([0, 0, 0, 255] => Err(NotSubnetMaskError))]
4005 fn test_ipv4_prefix_len_try_from_subnet_mask(
4006 subnet_mask: [u8; 4],
4007 ) -> Result<u8, NotSubnetMaskError> {
4008 let subnet_mask = Ipv4Addr::from(subnet_mask);
4009 PrefixLength::<Ipv4>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
4010 }
4011
4012 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(64))]
4013 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(63))]
4014 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
4015 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 1] => Err(NotSubnetMaskError))]
4016 #[test_case([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(0))]
4017 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] => Ok(128))]
4018 #[test_case([0, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
4019 fn test_ipv6_prefix_len_try_from_subnet_mask(
4020 subnet_mask: [u8; 16],
4021 ) -> Result<u8, NotSubnetMaskError> {
4022 let subnet_mask = Ipv6Addr::from(subnet_mask);
4023 PrefixLength::<Ipv6>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
4024 }
4025
4026 #[test_case(0 => true)]
4027 #[test_case(1 => true)]
4028 #[test_case(32 => true)]
4029 #[test_case(33 => false)]
4030 #[test_case(128 => false)]
4031 #[test_case(129 => false)]
4032 #[test_case(255 => false)]
4033 fn test_ipv4_prefix_len_new(prefix_len: u8) -> bool {
4034 PrefixLength::<Ipv4>::new(prefix_len).is_ok()
4035 }
4036
4037 #[test_case(0 => true)]
4038 #[test_case(1 => true)]
4039 #[test_case(32 => true)]
4040 #[test_case(33 => true)]
4041 #[test_case(128 => true)]
4042 #[test_case(129 => false)]
4043 #[test_case(255 => false)]
4044 fn test_ipv6_prefix_len_new(prefix_len: u8) -> bool {
4045 PrefixLength::<Ipv6>::new(prefix_len).is_ok()
4046 }
4047
4048 #[test_case(0 => [0, 0, 0, 0])]
4049 #[test_case(6 => [252, 0, 0, 0])]
4050 #[test_case(16 => [255, 255, 0, 0])]
4051 #[test_case(25 => [255, 255, 255, 128])]
4052 #[test_case(32 => [255, 255, 255, 255])]
4053 fn test_ipv4_prefix_len_get_mask(prefix_len: u8) -> [u8; 4] {
4054 let Ipv4Addr(inner) = PrefixLength::<Ipv4>::new(prefix_len).unwrap().get_mask();
4055 inner
4056 }
4057
4058 #[test_case(0 => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
4059 #[test_case(6 => [0xFC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
4060 #[test_case(64 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])]
4061 #[test_case(65 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0])]
4062 #[test_case(128 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])]
4063 fn test_ipv6_prefix_len_get_mask(prefix_len: u8) -> [u8; 16] {
4064 let Ipv6Addr(inner) = PrefixLength::<Ipv6>::new(prefix_len).unwrap().get_mask();
4065 inner
4066 }
4067
4068 #[test]
4069 fn test_ipv6_solicited_node() {
4070 let addr = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
4071 let solicited = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
4072 assert_eq!(addr.to_solicited_node_address().get(), solicited);
4073 }
4074
4075 #[test]
4076 fn test_ipv6_address_types() {
4077 assert!(!Ipv6Addr::from([0; 16]).is_specified());
4078 assert!(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1]).is_loopback());
4079 let link_local = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
4080 assert!(link_local.is_link_local());
4081 assert!(link_local.is_valid_unicast());
4082 assert!(link_local.to_solicited_node_address().is_multicast());
4083 let global_unicast = Ipv6Addr::new([0x80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
4084 assert!(global_unicast.is_valid_unicast());
4085 assert!(global_unicast.to_solicited_node_address().is_multicast());
4086
4087 let multi = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
4088 assert!(multi.is_multicast());
4089 assert!(!multi.is_valid_unicast());
4090 }
4091
4092 #[test]
4093 fn test_const_witness() {
4094 assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
4097 assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
4098 assert!(Ipv4::LIMITED_BROADCAST_ADDRESS.0.is_specified());
4099 assert!(Ipv4::ALL_ROUTERS_MULTICAST_ADDRESS.0.is_multicast());
4100 assert!(Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4101 assert!(Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4102 }
4103
4104 #[test]
4105 fn test_ipv6_scope() {
4106 use Ipv6ReservedScope::*;
4107 use Ipv6Scope::*;
4108 use Ipv6UnassignedScope::*;
4109
4110 assert_eq!(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network.scope(), SiteLocal);
4112 assert_eq!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.scope(), LinkLocal);
4113 assert_eq!(Ipv6::UNSPECIFIED_ADDRESS.scope(), Global);
4114
4115 let assert_scope = |value, scope| {
4117 let mut addr = Ipv6::MULTICAST_SUBNET.network;
4118 addr.0[1] |= value;
4120 assert_eq!(addr.scope(), scope);
4121 };
4122 assert_scope(0, Reserved(Scope0));
4123 assert_scope(1, InterfaceLocal);
4124 assert_scope(2, LinkLocal);
4125 assert_scope(3, Reserved(Scope3));
4126 assert_scope(4, AdminLocal);
4127 assert_scope(5, SiteLocal);
4128 assert_scope(6, Unassigned(Scope6));
4129 assert_scope(7, Unassigned(Scope7));
4130 assert_scope(8, OrganizationLocal);
4131 assert_scope(9, Unassigned(Scope9));
4132 assert_scope(0xA, Unassigned(ScopeA));
4133 assert_scope(0xB, Unassigned(ScopeB));
4134 assert_scope(0xC, Unassigned(ScopeC));
4135 assert_scope(0xD, Unassigned(ScopeD));
4136 assert_scope(0xE, Global);
4137 assert_scope(0xF, Reserved(ScopeF));
4138 }
4139
4140 #[test]
4141 fn test_ipv6_multicast_scope_id() {
4142 const ALL_SCOPES: &[Ipv6Scope] = &[
4143 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope0),
4144 Ipv6Scope::InterfaceLocal,
4145 Ipv6Scope::LinkLocal,
4146 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope3),
4147 Ipv6Scope::AdminLocal,
4148 Ipv6Scope::SiteLocal,
4149 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope6),
4150 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope7),
4151 Ipv6Scope::OrganizationLocal,
4152 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope9),
4153 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeA),
4154 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeB),
4155 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeC),
4156 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeD),
4157 Ipv6Scope::Global,
4158 Ipv6Scope::Reserved(Ipv6ReservedScope::ScopeF),
4159 ];
4160 for (i, a) in ALL_SCOPES.iter().enumerate() {
4161 assert_eq!(a.multicast_scope_id(), i.try_into().unwrap());
4162 }
4163 }
4164
4165 #[test]
4166 fn test_ipv4_embedded() {
4167 assert_eq!(
4170 Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_compatible(),
4171 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4])
4172 );
4173 assert_eq!(
4174 Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_mapped().get(),
4175 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]),
4176 );
4177
4178 let compatible = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4]);
4181 let mapped = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]);
4182 let not_embedded = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 1, 2, 3, 4]);
4183 let v4 = Ipv4Addr::new([1, 2, 3, 4]);
4184
4185 assert_eq!(compatible.to_ipv4_compatible(), Some(v4));
4186 assert_eq!(compatible.to_ipv4_mapped(), None);
4187
4188 assert_eq!(mapped.to_ipv4_compatible(), None);
4189 assert_eq!(mapped.to_ipv4_mapped(), Some(v4));
4190
4191 assert_eq!(not_embedded.to_ipv4_compatible(), None);
4192 assert_eq!(not_embedded.to_ipv4_mapped(), None);
4193
4194 assert_eq!(
4195 NonMappedAddr::new(compatible),
4196 Some(unsafe { NonMappedAddr::new_unchecked(compatible) })
4197 );
4198 assert_eq!(NonMappedAddr::new(mapped), None);
4199 assert_eq!(
4200 NonMappedAddr::new(not_embedded),
4201 Some(unsafe { NonMappedAddr::new_unchecked(not_embedded) })
4202 );
4203 assert_eq!(NonMappedAddr::new(v4), Some(unsafe { NonMappedAddr::new_unchecked(v4) }));
4204 }
4205
4206 #[test]
4207 fn test_common_prefix_len_ipv6() {
4208 let ip1 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4209 let ip2 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4210 let ip3 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4211 let ip4 = Ipv6Addr::from([0xFF, 0xFF, 0xC0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4212 let compare_with_ip1 = |target, expect| {
4213 assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4214 };
4215 compare_with_ip1(ip1, 128);
4216 compare_with_ip1(ip2, 0);
4217 compare_with_ip1(ip3, 24);
4218 compare_with_ip1(ip4, 17);
4219 }
4220
4221 #[test]
4222 fn test_common_prefix_len_ipv4() {
4223 let ip1 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0]);
4224 let ip2 = Ipv4Addr::new([0, 0, 0, 0]);
4225 let ip3 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0xFF]);
4226 let ip4 = Ipv4Addr::new([0xFF, 0xFF, 0xC0, 0x20]);
4227 let compare_with_ip1 = |target, expect| {
4228 assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4229 };
4230 compare_with_ip1(ip1, 32);
4231 compare_with_ip1(ip2, 0);
4232 compare_with_ip1(ip3, 24);
4233 compare_with_ip1(ip4, 17);
4234 }
4235
4236 #[test]
4237 fn test_ipv6_display() {
4238 fn test_one(addr: Ipv6Addr, expect: Option<&str>) {
4242 let formatted = format!("{}", addr);
4243 if let Some(expect) = expect {
4244 assert_eq!(formatted, expect);
4245 }
4246
4247 let formatted_std = format!("{}", std::net::Ipv6Addr::from(addr.segments()));
4257 assert_eq!(formatted, formatted_std);
4258 }
4259
4260 test_one(Ipv6::UNSPECIFIED_ADDRESS, Some("::"));
4261 test_one(*Ipv6::LOOPBACK_ADDRESS, Some("::1"));
4262 test_one(Ipv6::MULTICAST_SUBNET.network, Some("ff00::"));
4263 test_one(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network, Some("fe80::"));
4264 test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4265 test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4266 test_one(*Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::2"));
4267 test_one(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network, Some("fec0::"));
4268 test_one(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), Some("1::"));
4269 test_one(Ipv6Addr::new([0, 0, 0, 1, 2, 3, 4, 5]), Some("::1:2:3:4:5"));
4270
4271 for byte in 0u8..=255 {
4276 test_one(
4277 Ipv6Addr::new([
4278 u16::from(byte & 0b1),
4279 u16::from((byte & 0b10) >> 1),
4280 u16::from((byte & 0b100) >> 2),
4281 u16::from((byte & 0b1000) >> 3),
4282 u16::from((byte & 0b10000) >> 4),
4283 u16::from((byte & 0b100000) >> 5),
4284 u16::from((byte & 0b1000000) >> 6),
4285 u16::from((byte & 0b10000000) >> 7),
4286 ]),
4287 None,
4288 );
4289 }
4290 }
4291
4292 #[test_case(Ipv4::UNSPECIFIED_ADDRESS, Ipv4AddressClass::A; "first_class_a")]
4293 #[test_case(Ipv4Addr::new([127, 255, 255, 255]), Ipv4AddressClass::A; "last_class_a")]
4294 #[test_case(Ipv4Addr::new([128, 0, 0, 0]), Ipv4AddressClass::B; "first_class_b")]
4295 #[test_case(Ipv4Addr::new([191, 255, 255, 255]), Ipv4AddressClass::B; "last_class_b")]
4296 #[test_case(Ipv4Addr::new([192, 0, 0, 0]), Ipv4AddressClass::C; "first_class_c")]
4297 #[test_case(Ipv4Addr::new([223, 255, 255, 255]), Ipv4AddressClass::C; "last_class_c")]
4298 #[test_case(Ipv4Addr::new([224, 0, 0, 0]), Ipv4AddressClass::D; "first_class_d")]
4299 #[test_case(Ipv4Addr::new([239, 255, 255, 255]), Ipv4AddressClass::D; "last_class_d")]
4300 #[test_case(Ipv4Addr::new([240, 0, 0, 0]), Ipv4AddressClass::E; "first_class_e")]
4301 #[test_case(Ipv4Addr::new([255, 255, 255, 255]), Ipv4AddressClass::E; "last_class_e")]
4302 fn ipv4addr_class(addr: Ipv4Addr, class: Ipv4AddressClass) {
4303 assert_eq!(addr.class(), class)
4304 }
4305
4306 #[test_case(
4307 Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 24).unwrap(),
4308 Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap()
4309 ; "ipv4_same_prefix")]
4310 #[test_case(
4311 Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap(),
4312 Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 32).unwrap()
4313 ; "ipv4_by_prefix")]
4314 #[test_case(
4315 Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4316 Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap()
4317 ; "ipv6_same_prefix")]
4318 #[test_case(
4319 Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4320 Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 128).unwrap()
4321 ; "ipv6_by_prefix")]
4322 fn subnet_ord<A: core::cmp::Ord>(a: Subnet<A>, b: Subnet<A>) {
4323 assert!(a < b);
4324 }
4325
4326 #[cfg(feature = "std")]
4327 mod std_tests {
4328 use super::*;
4329
4330 #[test]
4331 fn test_conversions() {
4332 let v4 = Ipv4Addr::new([127, 0, 0, 1]);
4333 let v6 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
4334 let std_v4 = net::Ipv4Addr::new(127, 0, 0, 1);
4335 let std_v6 = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
4336
4337 let converted: IpAddr = net::IpAddr::V4(std_v4).into();
4338 assert_eq!(converted, IpAddr::V4(v4));
4339 let converted: IpAddr = net::IpAddr::V6(std_v6).into();
4340 assert_eq!(converted, IpAddr::V6(v6));
4341
4342 let converted: net::IpAddr = IpAddr::V4(v4).into();
4343 assert_eq!(converted, net::IpAddr::V4(std_v4));
4344 let converted: net::IpAddr = IpAddr::V6(v6).into();
4345 assert_eq!(converted, net::IpAddr::V6(std_v6));
4346
4347 let converted: Ipv4Addr = std_v4.into();
4348 assert_eq!(converted, v4);
4349 let converted: Ipv6Addr = std_v6.into();
4350 assert_eq!(converted, v6);
4351
4352 let converted: net::Ipv4Addr = v4.into();
4353 assert_eq!(converted, std_v4);
4354 let converted: net::Ipv6Addr = v6.into();
4355 assert_eq!(converted, std_v6);
4356 }
4357 }
4358}
4359
4360#[cfg(test)]
4362mod macro_test {
4363 use super::*;
4364
4365 fn assert_ip_generic_is<T, I, Other>()
4367 where
4368 I: Ip,
4369 T: GenericOverIp<I, Type = Other>,
4370 {
4371 }
4374
4375 macro_rules! assert_ip_generic {
4376 ($name:ident, Ip $(,$($param:ident),*)?) => {
4377 assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4378 assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4379 assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4380 assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4381 };
4382 ($name:ident, IpAddress $(,$($param:ident),*)?) => {
4383 assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4384 assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4385 assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4386 assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4387 };
4388 ($name:ident $(,$($param:ident),*)?) => {
4389 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4390 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4391 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4392 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4393 };
4394 }
4395
4396 #[test]
4397 fn struct_with_ip_version_parameter() {
4398 #[allow(dead_code)]
4399 #[derive(GenericOverIp)]
4400 #[generic_over_ip(I, Ip)]
4401 struct Generic<I: Ip> {
4402 addr: I::Addr,
4403 }
4404
4405 assert_ip_generic!(Generic, Ip);
4406 }
4407
4408 #[test]
4409 fn struct_with_unbounded_ip_version_parameter() {
4410 #[allow(dead_code)]
4411 #[derive(GenericOverIp)]
4412 #[generic_over_ip(I, Ip)]
4413 struct Generic<I> {
4414 addr: core::marker::PhantomData<I>,
4415 }
4416
4417 assert_ip_generic!(Generic, Ip);
4418 }
4419
4420 #[test]
4421 fn struct_with_ip_address_parameter() {
4422 #[allow(dead_code)]
4423 #[derive(GenericOverIp)]
4424 #[generic_over_ip(A, IpAddress)]
4425 struct Generic<A: IpAddress> {
4426 addr: A,
4427 }
4428
4429 assert_ip_generic!(Generic, IpAddress);
4430 }
4431
4432 #[test]
4433 fn struct_with_unbounded_ip_address_parameter() {
4434 #[allow(dead_code)]
4435 #[derive(GenericOverIp)]
4436 #[generic_over_ip(A, IpAddress)]
4437 struct Generic<A> {
4438 addr: A,
4439 }
4440
4441 assert_ip_generic!(Generic, IpAddress);
4442 }
4443
4444 #[test]
4445 fn struct_with_generic_over_ip_parameter() {
4446 #[derive(GenericOverIp)]
4447 #[generic_over_ip(I, Ip)]
4448 struct InnerGeneric<I: Ip> {
4449 addr: I::Addr,
4450 }
4451
4452 #[derive(GenericOverIp)]
4453 #[generic_over_ip(T, GenericOverIp)]
4454 struct Generic<T> {
4455 foo: T,
4456 }
4457
4458 fn do_something<I: Ip>(g: Generic<InnerGeneric<I>>) {
4459 I::map_ip(
4460 g,
4461 |g| {
4462 let _: Ipv4Addr = g.foo.addr;
4463 },
4464 |g| {
4465 let _: Ipv6Addr = g.foo.addr;
4466 },
4467 )
4468 }
4469
4470 do_something::<Ipv4>(Generic { foo: InnerGeneric { addr: Ipv4::UNSPECIFIED_ADDRESS } });
4471
4472 do_something::<Ipv6>(Generic { foo: InnerGeneric { addr: Ipv6::UNSPECIFIED_ADDRESS } });
4473 }
4474
4475 #[test]
4476 fn enum_with_ip_version_parameter() {
4477 #[allow(dead_code)]
4478 #[derive(GenericOverIp)]
4479 #[generic_over_ip(I, Ip)]
4480 enum Generic<I: Ip> {
4481 A(I::Addr),
4482 B(I::Addr),
4483 }
4484
4485 assert_ip_generic!(Generic, Ip);
4486 }
4487
4488 #[test]
4489 fn enum_with_unbounded_ip_version_parameter() {
4490 #[allow(dead_code)]
4491 #[derive(GenericOverIp)]
4492 #[generic_over_ip(I, Ip)]
4493 enum Generic<I> {
4494 A(core::marker::PhantomData<I>),
4495 B(core::marker::PhantomData<I>),
4496 }
4497
4498 assert_ip_generic!(Generic, Ip);
4499 }
4500
4501 #[test]
4502 fn enum_with_ip_address_parameter() {
4503 #[allow(dead_code)]
4504 #[derive(GenericOverIp)]
4505 #[generic_over_ip(A, IpAddress)]
4506 enum Generic<A: IpAddress> {
4507 A(A),
4508 B(A),
4509 }
4510
4511 assert_ip_generic!(Generic, IpAddress);
4512 }
4513
4514 #[test]
4515 fn enum_with_unbounded_ip_address_parameter() {
4516 #[allow(dead_code)]
4517 #[derive(GenericOverIp)]
4518 #[generic_over_ip(A, IpAddress)]
4519 enum Generic<A> {
4520 A(A),
4521 B(A),
4522 }
4523
4524 assert_ip_generic!(Generic, IpAddress);
4525 }
4526
4527 #[test]
4528 fn struct_with_ip_version_and_other_parameters() {
4529 #[allow(dead_code)]
4530 #[derive(GenericOverIp)]
4531 #[generic_over_ip(I, Ip)]
4532 struct AddrAndDevice<I: Ip, D> {
4533 addr: I::Addr,
4534 device: D,
4535 }
4536 struct Device;
4537
4538 assert_ip_generic!(AddrAndDevice, Ip, Device);
4539 }
4540
4541 #[test]
4542 fn enum_with_ip_version_and_other_parameters() {
4543 #[allow(dead_code)]
4544 #[derive(GenericOverIp)]
4545 #[generic_over_ip(I, Ip)]
4546 enum AddrOrDevice<I: Ip, D> {
4547 Addr(I::Addr),
4548 Device(D),
4549 }
4550 struct Device;
4551
4552 assert_ip_generic!(AddrOrDevice, Ip, Device);
4553 }
4554
4555 #[test]
4556 fn struct_with_ip_address_and_other_parameters() {
4557 #[allow(dead_code)]
4558 #[derive(GenericOverIp)]
4559 #[generic_over_ip(A, IpAddress)]
4560 struct AddrAndDevice<A: IpAddress, D> {
4561 addr: A,
4562 device: D,
4563 }
4564 struct Device;
4565
4566 assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4567 }
4568
4569 #[test]
4570 fn struct_with_unbounded_ip_address_and_other_parameters() {
4571 #[allow(dead_code)]
4572 #[derive(GenericOverIp)]
4573 #[generic_over_ip(A, IpAddress)]
4574 struct AddrAndDevice<A, D> {
4575 addr: A,
4576 device: D,
4577 }
4578 struct Device;
4579
4580 assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4581 }
4582
4583 #[test]
4584 fn enum_with_ip_address_and_other_parameters() {
4585 #[allow(dead_code)]
4586 #[derive(GenericOverIp, Debug, PartialEq)]
4587 #[generic_over_ip(A, IpAddress)]
4588 enum AddrOrDevice<A: IpAddress, D> {
4589 Addr(A),
4590 Device(D),
4591 }
4592 struct Device;
4593
4594 assert_ip_generic!(AddrOrDevice, IpAddress, Device);
4595 }
4596
4597 #[test]
4598 fn struct_invariant_over_ip() {
4599 #[allow(dead_code)]
4600 #[derive(GenericOverIp)]
4601 #[generic_over_ip()]
4602 struct Invariant(usize);
4603
4604 assert_ip_generic!(Invariant);
4605 }
4606
4607 #[test]
4608 fn enum_invariant_over_ip() {
4609 #[allow(dead_code)]
4610 #[derive(GenericOverIp)]
4611 #[generic_over_ip()]
4612 enum Invariant {
4613 Usize(usize),
4614 }
4615
4616 assert_ip_generic!(Invariant);
4617 }
4618
4619 #[test]
4620 fn struct_invariant_over_ip_with_other_params() {
4621 #[allow(dead_code)]
4622 #[derive(GenericOverIp)]
4623 #[generic_over_ip()]
4624 struct Invariant<B, C, D>(B, C, D);
4625
4626 assert_ip_generic!(Invariant, usize, bool, char);
4627 }
4628
4629 #[test]
4630 fn enum_invariant_over_ip_with_other_params() {
4631 #[allow(dead_code)]
4632 #[derive(GenericOverIp)]
4633 #[generic_over_ip()]
4634 enum Invariant<A, B, C> {
4635 A(A),
4636 B(B),
4637 C(C),
4638 }
4639
4640 assert_ip_generic!(Invariant, usize, bool, char);
4641 }
4642
4643 #[test]
4644 fn struct_with_ip_version_extension_parameter() {
4645 trait FakeIpExt: Ip {
4646 type Associated;
4647 }
4648 impl FakeIpExt for Ipv4 {
4649 type Associated = u8;
4650 }
4651 impl FakeIpExt for Ipv6 {
4652 type Associated = u16;
4653 }
4654
4655 #[allow(dead_code)]
4656 #[derive(GenericOverIp)]
4657 #[generic_over_ip(I, Ip)]
4658 struct Generic<I: FakeIpExt> {
4659 field: I::Associated,
4660 }
4661
4662 assert_ip_generic!(Generic, Ip);
4663 }
4664
4665 #[test]
4666 fn struct_with_ip_version_extension_parameter_but_no_ip_bound() {
4667 trait FakeIpExt: Ip {
4668 type Associated;
4669 }
4670 impl FakeIpExt for Ipv4 {
4671 type Associated = u8;
4672 }
4673 impl FakeIpExt for Ipv6 {
4674 type Associated = u16;
4675 }
4676
4677 #[allow(dead_code)]
4678 #[derive(GenericOverIp)]
4679 #[generic_over_ip(I, Ip)]
4680 struct Generic<I: FakeIpExt> {
4681 field: I::Associated,
4682 }
4683
4684 assert_ip_generic!(Generic, Ip);
4685 }
4686
4687 #[test]
4688 fn struct_with_ip_address_extension_parameter() {
4689 trait FakeIpAddressExt: IpAddress {
4690 type Associated;
4691 }
4692 impl FakeIpAddressExt for Ipv4Addr {
4693 type Associated = u8;
4694 }
4695 impl FakeIpAddressExt for Ipv6Addr {
4696 type Associated = u16;
4697 }
4698
4699 #[allow(dead_code)]
4700 #[derive(GenericOverIp)]
4701 #[generic_over_ip(A, IpAddress)]
4702 struct Generic<A: IpAddress + FakeIpAddressExt> {
4703 field: A::Associated,
4704 }
4705
4706 assert_ip_generic!(Generic, IpAddress);
4707 }
4708
4709 #[test]
4710 fn type_with_lifetime_and_ip_parameter() {
4711 #[allow(dead_code)]
4712 #[derive(GenericOverIp)]
4713 #[generic_over_ip(I, Ip)]
4714 struct Generic<'a, I: Ip> {
4715 field: &'a I::Addr,
4716 }
4717
4718 assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv4, Generic<'static, Ipv4>>();
4719 assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv6, Generic<'static, Ipv6>>();
4720 assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv4, Generic<'static, Ipv4>>();
4721 assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv6, Generic<'static, Ipv6>>();
4722 }
4723
4724 #[test]
4725 fn type_with_lifetime_and_no_ip_parameter() {
4726 #[allow(dead_code)]
4727 #[derive(GenericOverIp)]
4728 #[generic_over_ip()]
4729 struct Generic<'a> {
4730 field: &'a (),
4731 }
4732
4733 assert_ip_generic_is::<Generic<'static>, Ipv4, Generic<'static>>();
4734 assert_ip_generic_is::<Generic<'static>, Ipv6, Generic<'static>>();
4735 }
4736
4737 #[test]
4738 fn type_with_params_list_with_trailing_comma() {
4739 trait IpExtensionTraitWithVeryLongName {}
4740 trait OtherIpExtensionTraitWithVeryLongName {}
4741 trait LongNameToForceFormatterToBreakLineAndAddTrailingComma {}
4742 #[allow(dead_code)]
4744 #[derive(GenericOverIp)]
4745 #[generic_over_ip(I, Ip)]
4746 struct Generic<
4747 I: Ip
4748 + IpExtensionTraitWithVeryLongName
4749 + OtherIpExtensionTraitWithVeryLongName
4750 + LongNameToForceFormatterToBreakLineAndAddTrailingComma,
4751 > {
4752 field: I::Addr,
4753 }
4754 }
4755}