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