1use core::fmt::{self, Debug, Display, Formatter};
59use core::hash::Hash;
60use core::mem;
61use core::ops::{Deref, DerefMut};
62
63#[cfg(feature = "std")]
64use std::net;
65#[cfg(feature = "std")]
66use std::sync::Arc;
67
68pub use net_types_macros::GenericOverIp;
69use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
70
71use crate::{
72 LinkLocalAddr, LinkLocalAddress, MappedAddress, MulticastAddr, MulticastAddress, NonMappedAddr,
73 NonMulticastAddr, Scope, ScopeableAddress, SpecifiedAddr, SpecifiedAddress, UnicastAddr,
74 UnicastAddress, Witness, sealed,
75};
76
77#[allow(missing_docs)]
84#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
85pub enum IpVersion {
86 V4,
87 V6,
88}
89
90#[macro_export]
103macro_rules! for_any_ip_version {
104 ($ip_version:expr, $type_param:ident, $expression:expr) => {
105 match $ip_version {
106 $crate::ip::IpVersion::V4 => {
107 type $type_param = $crate::ip::Ipv4;
108 $expression
109 }
110 $crate::ip::IpVersion::V6 => {
111 type $type_param = $crate::ip::Ipv6;
112 $expression
113 }
114 }
115 };
116}
117
118#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, GenericOverIp)]
126#[generic_over_ip(I, Ip)]
127pub struct IpVersionMarker<I: Ip> {
128 _marker: core::marker::PhantomData<I>,
129}
130
131impl<I: Ip> IpVersionMarker<I> {
132 pub const fn new() -> Self {
136 Self { _marker: core::marker::PhantomData }
137 }
138}
139
140impl<I: Ip> Default for IpVersionMarker<I> {
141 fn default() -> Self {
142 Self { _marker: core::marker::PhantomData }
143 }
144}
145
146impl<I: Ip> Debug for IpVersionMarker<I> {
147 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
148 write!(f, "IpVersionMarker<{}>", I::NAME)
149 }
150}
151
152#[allow(missing_docs)]
161#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
162pub enum IpAddr<V4 = Ipv4Addr, V6 = Ipv6Addr> {
163 V4(V4),
164 V6(V6),
165}
166
167impl<V4: Display, V6: Display> Display for IpAddr<V4, V6> {
168 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
169 match self {
170 Self::V4(v4) => v4.fmt(f),
171 Self::V6(v6) => v6.fmt(f),
172 }
173 }
174}
175
176impl<V4, V6> IpAddr<V4, V6> {
177 pub fn transpose<W: IpAddrWitness<V4 = V4, V6 = V6>>(self) -> W {
184 match self {
185 IpAddr::V4(addr) => W::from_v4(addr),
186 IpAddr::V6(addr) => W::from_v6(addr),
187 }
188 }
189}
190
191impl<A: IpAddress> From<A> for IpAddr {
192 #[inline]
193 fn from(addr: A) -> IpAddr {
194 addr.to_ip_addr()
195 }
196}
197
198impl<A: IpAddress, const N: usize> From<[A; N]> for IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
199 #[inline]
200 fn from(addrs: [A; N]) -> Self {
201 A::array_into_ip_addr(addrs)
202 }
203}
204
205#[cfg(feature = "std")]
206impl From<net::IpAddr> for IpAddr {
207 #[inline]
208 fn from(addr: net::IpAddr) -> IpAddr {
209 match addr {
210 net::IpAddr::V4(addr) => IpAddr::V4(addr.into()),
211 net::IpAddr::V6(addr) => IpAddr::V6(addr.into()),
212 }
213 }
214}
215
216#[cfg(feature = "std")]
217impl From<IpAddr> for net::IpAddr {
218 fn from(addr: IpAddr) -> net::IpAddr {
219 match addr {
220 IpAddr::V4(addr) => net::IpAddr::V4(addr.into()),
221 IpAddr::V6(addr) => net::IpAddr::V6(addr.into()),
222 }
223 }
224}
225
226impl IpVersion {
227 #[inline]
231 pub fn version_number(self) -> u8 {
232 match self {
233 IpVersion::V4 => 4,
234 IpVersion::V6 => 6,
235 }
236 }
237
238 #[inline]
240 pub fn is_v4(self) -> bool {
241 self == IpVersion::V4
242 }
243
244 #[inline]
246 pub fn is_v6(self) -> bool {
247 self == IpVersion::V6
248 }
249}
250
251#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
254pub struct Mtu(u32);
255
256impl Mtu {
257 pub const fn new(mtu: u32) -> Self {
259 Self(mtu)
260 }
261
262 pub const fn get(&self) -> u32 {
264 let Self(mtu) = self;
265 *mtu
266 }
267
268 pub const fn max() -> Self {
270 Self(u32::MAX)
271 }
272
273 pub const fn no_limit() -> Self {
277 Self::max()
278 }
279}
280
281impl From<Mtu> for u32 {
282 fn from(Mtu(mtu): Mtu) -> Self {
283 mtu
284 }
285}
286
287impl From<Mtu> for usize {
288 fn from(Mtu(mtu): Mtu) -> Self {
289 mtu.try_into().expect("mtu must fit usize")
290 }
291}
292
293pub trait Ip:
308 Sized
309 + Clone
310 + Copy
311 + Debug
312 + Default
313 + Eq
314 + Hash
315 + Ord
316 + PartialEq
317 + PartialOrd
318 + Send
319 + Sync
320 + sealed::Sealed
321 + 'static
322{
323 const VERSION: IpVersion;
327
328 const VERSION_MARKER: IpVersionMarker<Self>;
330
331 const UNSPECIFIED_ADDRESS: Self::Addr;
335
336 const LOOPBACK_ADDRESS: SpecifiedAddr<Self::Addr>;
343
344 const LOOPBACK_SUBNET: Subnet<Self::Addr>;
349
350 const MULTICAST_SUBNET: Subnet<Self::Addr>;
352
353 const LINK_LOCAL_UNICAST_SUBNET: Subnet<Self::Addr>;
363
364 const ALL_ADDRS_SUBNET: Subnet<Self::Addr> =
366 Subnet { network: Self::UNSPECIFIED_ADDRESS, prefix: 0 };
367
368 const NAME: &'static str;
370
371 const MINIMUM_LINK_MTU: Mtu;
378
379 type Addr: IpAddress<Version = Self>
383 + GenericOverIp<Self, Type = Self::Addr>
384 + GenericOverIp<Ipv4, Type = Ipv4Addr>
385 + GenericOverIp<Ipv6, Type = Ipv6Addr>;
386
387 fn map_ip<
418 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
419 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
420 >(
421 input: In,
422 v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
423 v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
424 ) -> Out;
425
426 fn map_ip_in<
433 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
434 Out,
435 >(
436 input: In,
437 v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> Out,
438 v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> Out,
439 ) -> Out {
440 Self::map_ip::<_, IpInvariant<_>>(
441 input,
442 |input| IpInvariant(v4(input)),
443 |input| IpInvariant(v6(input)),
444 )
445 .into_inner()
446 }
447
448 fn map_ip_out<
455 In,
456 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
457 >(
458 input: In,
459 v4: impl FnOnce(In) -> <Out as GenericOverIp<Ipv4>>::Type,
460 v6: impl FnOnce(In) -> <Out as GenericOverIp<Ipv6>>::Type,
461 ) -> Out {
462 Self::map_ip(
463 IpInvariant(input),
464 |IpInvariant(input)| v4(input),
465 |IpInvariant(input)| v6(input),
466 )
467 }
468}
469
470#[macro_export]
539macro_rules! map_ip_twice {
540 ($ip:ident, $input:expr, $fn:expr $(,)?) => {
544 $crate::map_ip_twice!($ip as $ip, $input, $fn)
545 };
546 ($ip:ty, $input:expr, $fn:expr $(,)?) => {
550 <$ip as $crate::ip::Ip>::map_ip($input, { $fn }, { $fn })
551 };
552 ($ip:ty as $iptypealias:ident, $input:expr, $fn:expr $(,)?) => {
553 <$ip as $crate::ip::Ip>::map_ip(
554 $input,
555 {
556 #[allow(dead_code)]
557 type $iptypealias = $crate::ip::Ipv4;
558 $fn
559 },
560 {
561 #[allow(dead_code)]
562 type $iptypealias = $crate::ip::Ipv6;
563 $fn
564 },
565 )
566 };
567}
568
569#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
576pub enum Ipv4 {}
577
578impl Default for Ipv4 {
579 fn default() -> Ipv4 {
580 panic!("Ipv4 default")
581 }
582}
583
584impl sealed::Sealed for Ipv4 {}
585
586impl Ip for Ipv4 {
587 const VERSION: IpVersion = IpVersion::V4;
588 const VERSION_MARKER: IpVersionMarker<Self> = IpVersionMarker::new();
589
590 const UNSPECIFIED_ADDRESS: Ipv4Addr = Ipv4Addr::new([0, 0, 0, 0]);
593 const LOOPBACK_ADDRESS: SpecifiedAddr<Ipv4Addr> =
602 unsafe { SpecifiedAddr::new_unchecked(Ipv4Addr::new([127, 0, 0, 1])) };
603 const LOOPBACK_SUBNET: Subnet<Ipv4Addr> =
607 Subnet { network: Ipv4Addr::new([127, 0, 0, 0]), prefix: 8 };
608 const MULTICAST_SUBNET: Subnet<Ipv4Addr> = Self::CLASS_D_SUBNET;
612 const LINK_LOCAL_UNICAST_SUBNET: Subnet<Ipv4Addr> =
617 Subnet { network: Ipv4Addr::new([169, 254, 0, 0]), prefix: 16 };
618 const NAME: &'static str = "IPv4";
619 const MINIMUM_LINK_MTU: Mtu = Mtu(68);
626 type Addr = Ipv4Addr;
627
628 fn map_ip<
629 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
630 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
631 >(
632 input: In,
633 v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
634 _v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
635 ) -> Out {
636 v4(input)
637 }
638}
639
640impl Ipv4 {
641 pub const LIMITED_BROADCAST_ADDRESS: SpecifiedAddr<Ipv4Addr> =
651 unsafe { SpecifiedAddr::new_unchecked(Ipv4Addr::new([255, 255, 255, 255])) };
652
653 pub const CLASS_A_SUBNET: Subnet<Ipv4Addr> =
659 Subnet { network: Ipv4Addr::new([0, 0, 0, 0]), prefix: 1 };
660
661 pub const CLASS_B_SUBNET: Subnet<Ipv4Addr> =
667 Subnet { network: Ipv4Addr::new([128, 0, 0, 0]), prefix: 2 };
668
669 pub const CLASS_C_SUBNET: Subnet<Ipv4Addr> =
675 Subnet { network: Ipv4Addr::new([192, 0, 0, 0]), prefix: 3 };
676
677 pub const CLASS_D_SUBNET: Subnet<Ipv4Addr> =
685 Subnet { network: Ipv4Addr::new([224, 0, 0, 0]), prefix: 4 };
686
687 pub const CLASS_E_SUBNET: Subnet<Ipv4Addr> =
697 Subnet { network: Ipv4Addr::new([240, 0, 0, 0]), prefix: 4 };
698
699 pub const LINK_LOCAL_MULTICAST_SUBNET: Subnet<Ipv4Addr> =
704 Subnet { network: Ipv4Addr::new([224, 0, 0, 0]), prefix: 24 };
705
706 pub const ALL_SYSTEMS_MULTICAST_ADDRESS: MulticastAddr<Ipv4Addr> =
711 unsafe { MulticastAddr::new_unchecked(Ipv4Addr::new([224, 0, 0, 1])) };
712
713 pub const ALL_ROUTERS_MULTICAST_ADDRESS: MulticastAddr<Ipv4Addr> =
718 unsafe { MulticastAddr::new_unchecked(Ipv4Addr::new([224, 0, 0, 2])) };
719}
720
721#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
728pub enum Ipv6 {}
729
730impl Default for Ipv6 {
731 fn default() -> Ipv6 {
732 panic!("Ipv6 default")
733 }
734}
735
736impl sealed::Sealed for Ipv6 {}
737
738impl Ip for Ipv6 {
739 const VERSION: IpVersion = IpVersion::V6;
740 const VERSION_MARKER: IpVersionMarker<Self> = IpVersionMarker::new();
741 const UNSPECIFIED_ADDRESS: Ipv6Addr = Ipv6Addr::new([0; 8]);
757 const LOOPBACK_ADDRESS: SpecifiedAddr<Ipv6Addr> =
777 unsafe { SpecifiedAddr::new_unchecked(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1])) };
778 const LOOPBACK_SUBNET: Subnet<Ipv6Addr> =
786 Subnet { network: Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1]), prefix: 128 };
787 const MULTICAST_SUBNET: Subnet<Ipv6Addr> =
792 Subnet { network: Ipv6Addr::new([0xff00, 0, 0, 0, 0, 0, 0, 0]), prefix: 8 };
793 const LINK_LOCAL_UNICAST_SUBNET: Subnet<Ipv6Addr> =
803 Subnet { network: Ipv6Addr::new([0xfe80, 0, 0, 0, 0, 0, 0, 0]), prefix: 10 };
804 const NAME: &'static str = "IPv6";
805 const MINIMUM_LINK_MTU: Mtu = Mtu(1280);
817 type Addr = Ipv6Addr;
818
819 fn map_ip<
820 In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
821 Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
822 >(
823 input: In,
824 _v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
825 v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
826 ) -> Out {
827 v6(input)
828 }
829}
830
831impl Ipv6 {
832 pub const LOOPBACK_IPV6_ADDRESS: UnicastAddr<Ipv6Addr> =
839 unsafe { UnicastAddr::new_unchecked(Ipv6::LOOPBACK_ADDRESS.0) };
840
841 pub const ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS: MulticastAddr<Ipv6Addr> =
846 unsafe { MulticastAddr::new_unchecked(Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0, 0, 1])) };
847
848 pub const ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS: MulticastAddr<Ipv6Addr> =
853 unsafe { MulticastAddr::new_unchecked(Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0, 0, 2])) };
854
855 pub const SITE_LOCAL_UNICAST_SUBNET: Subnet<Ipv6Addr> =
869 Subnet { network: Ipv6Addr::new([0xfec0, 0, 0, 0, 0, 0, 0, 0]), prefix: 10 };
870
871 pub const UNICAST_INTERFACE_IDENTIFIER_BITS: u8 = 64;
896
897 pub const FLOW_LABEL_BITS: u8 = 20;
901}
902
903pub trait IpAddress:
910 Sized
911 + Eq
912 + PartialEq
913 + PartialOrd
914 + Ord
915 + Hash
916 + Copy
917 + Display
918 + Debug
919 + Default
920 + Sync
921 + Send
922 + LinkLocalAddress
923 + ScopeableAddress
924 + GenericOverIp<Self::Version, Type = Self>
925 + GenericOverIp<Ipv4, Type = Ipv4Addr>
926 + GenericOverIp<Ipv6, Type = Ipv6Addr>
927 + sealed::Sealed
928 + 'static
929{
930 const BYTES: u8;
934
935 type Version: Ip<Addr = Self>;
939
940 fn bytes(&self) -> &[u8];
942
943 fn mask(&self, bits: u8) -> Self;
953
954 fn to_ip_addr(&self) -> IpAddr;
956
957 #[inline]
964 fn is_loopback(&self) -> bool {
965 Self::Version::LOOPBACK_SUBNET.contains(self)
966 }
967
968 fn common_prefix_len(&self, other: &Self) -> u8;
970
971 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool;
1031
1032 #[doc(hidden)]
1038 fn subnet_into_either(subnet: Subnet<Self>) -> SubnetEither;
1039
1040 #[doc(hidden)]
1041 fn array_into_ip_addr<const N: usize>(addrs: [Self; N])
1042 -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]>;
1043}
1044
1045impl<A: IpAddress> SpecifiedAddress for A {
1046 #[inline]
1053 fn is_specified(&self) -> bool {
1054 self != &A::Version::UNSPECIFIED_ADDRESS
1055 }
1056}
1057
1058macro_rules! map_ip_addr {
1061 ($val:expr, $method:ident) => {
1062 match $val {
1063 IpAddr::V4(a) => a.$method(),
1064 IpAddr::V6(a) => a.$method(),
1065 }
1066 };
1067}
1068
1069impl SpecifiedAddress for IpAddr {
1070 #[inline]
1075 fn is_specified(&self) -> bool {
1076 map_ip_addr!(self, is_specified)
1077 }
1078}
1079
1080impl<A: IpAddress> MulticastAddress for A {
1081 #[inline]
1088 fn is_multicast(&self) -> bool {
1089 <A as IpAddress>::Version::MULTICAST_SUBNET.contains(self)
1090 }
1091}
1092
1093impl MulticastAddress for IpAddr {
1094 #[inline]
1099 fn is_multicast(&self) -> bool {
1100 map_ip_addr!(self, is_multicast)
1101 }
1102}
1103
1104impl LinkLocalAddress for Ipv4Addr {
1105 #[inline]
1111 fn is_link_local(&self) -> bool {
1112 Ipv4::LINK_LOCAL_UNICAST_SUBNET.contains(self)
1113 || Ipv4::LINK_LOCAL_MULTICAST_SUBNET.contains(self)
1114 }
1115}
1116
1117impl LinkLocalAddress for Ipv6Addr {
1118 #[inline]
1128 fn is_link_local(&self) -> bool {
1129 Ipv6::LINK_LOCAL_UNICAST_SUBNET.contains(self)
1130 || (self.is_multicast() && self.scope() == Ipv6Scope::LinkLocal)
1131 || self == Ipv6::LOOPBACK_ADDRESS.deref()
1132 }
1133}
1134
1135impl LinkLocalAddress for IpAddr {
1136 #[inline]
1138 fn is_link_local(&self) -> bool {
1139 map_ip_addr!(self, is_link_local)
1140 }
1141}
1142
1143impl<A: IpAddress> MappedAddress for A {
1144 #[inline]
1155 fn is_non_mapped(&self) -> bool {
1156 A::Version::map_ip(self, |_addr_v4| true, |addr_v6| addr_v6.to_ipv4_mapped().is_none())
1157 }
1158}
1159
1160impl MappedAddress for IpAddr {
1161 #[inline]
1163 fn is_non_mapped(&self) -> bool {
1164 map_ip_addr!(self, is_non_mapped)
1165 }
1166}
1167
1168impl<I: Ip> GenericOverIp<I> for Ipv4Addr {
1169 type Type = I::Addr;
1170}
1171
1172impl<I: Ip> GenericOverIp<I> for Ipv6Addr {
1173 type Type = I::Addr;
1174}
1175
1176impl ScopeableAddress for Ipv4Addr {
1177 type Scope = ();
1178
1179 fn scope(&self) {}
1184}
1185
1186#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1193pub enum Ipv6Scope {
1194 InterfaceLocal,
1196 LinkLocal,
1198 RealmLocal,
1200 AdminLocal,
1202 SiteLocal,
1218 OrganizationLocal,
1220 Global,
1222 Reserved(Ipv6ReservedScope),
1226 Unassigned(Ipv6UnassignedScope),
1228}
1229
1230#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1234pub enum Ipv6ReservedScope {
1235 Scope0 = 0,
1237 ScopeF = 0xF,
1239}
1240
1241#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1244pub enum Ipv6UnassignedScope {
1245 Scope6 = 6,
1247 Scope7 = 7,
1249 Scope9 = 9,
1251 ScopeA = 0xA,
1253 ScopeB = 0xB,
1255 ScopeC = 0xC,
1257 ScopeD = 0xD,
1259}
1260
1261impl Scope for Ipv6Scope {
1262 #[inline]
1263 fn can_have_zone(&self) -> bool {
1264 matches!(self, Ipv6Scope::LinkLocal)
1284 }
1285}
1286
1287impl Ipv6Scope {
1288 pub const MULTICAST_SCOPE_ID_INTERFACE_LOCAL: u8 = 1;
1293
1294 pub const MULTICAST_SCOPE_ID_LINK_LOCAL: u8 = 2;
1298
1299 pub const MULTICAST_SCOPE_ID_REALM_LOCAL: u8 = 3;
1303
1304 pub const MULTICAST_SCOPE_ID_ADMIN_LOCAL: u8 = 4;
1308
1309 pub const MULTICAST_SCOPE_ID_SITE_LOCAL: u8 = 5;
1316
1317 pub const MULTICAST_SCOPE_ID_ORG_LOCAL: u8 = 8;
1322
1323 pub const MULTICAST_SCOPE_ID_GLOBAL: u8 = 0xE;
1327
1328 pub fn multicast_scope_id(&self) -> u8 {
1346 match self {
1347 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope0) => 0,
1348 Ipv6Scope::InterfaceLocal => Self::MULTICAST_SCOPE_ID_INTERFACE_LOCAL,
1349 Ipv6Scope::LinkLocal => Self::MULTICAST_SCOPE_ID_LINK_LOCAL,
1350 Ipv6Scope::RealmLocal => Self::MULTICAST_SCOPE_ID_REALM_LOCAL,
1351 Ipv6Scope::AdminLocal => Self::MULTICAST_SCOPE_ID_ADMIN_LOCAL,
1352 Ipv6Scope::SiteLocal => Self::MULTICAST_SCOPE_ID_SITE_LOCAL,
1353 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope6) => 6,
1354 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope7) => 7,
1355 Ipv6Scope::OrganizationLocal => Self::MULTICAST_SCOPE_ID_ORG_LOCAL,
1356 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope9) => 9,
1357 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeA) => 0xA,
1358 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeB) => 0xB,
1359 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeC) => 0xC,
1360 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeD) => 0xD,
1361 Ipv6Scope::Global => Self::MULTICAST_SCOPE_ID_GLOBAL,
1362 Ipv6Scope::Reserved(Ipv6ReservedScope::ScopeF) => 0xF,
1363 }
1364 }
1365}
1366
1367impl ScopeableAddress for Ipv6Addr {
1368 type Scope = Ipv6Scope;
1369
1370 #[inline]
1372 fn scope(&self) -> Ipv6Scope {
1373 if self.is_multicast() {
1374 use Ipv6ReservedScope::*;
1375 use Ipv6Scope::*;
1376 use Ipv6UnassignedScope::*;
1377
1378 match self.0[1] & 0xF {
1382 0 => Reserved(Scope0),
1383 Ipv6Scope::MULTICAST_SCOPE_ID_INTERFACE_LOCAL => InterfaceLocal,
1384 Ipv6Scope::MULTICAST_SCOPE_ID_LINK_LOCAL => LinkLocal,
1385 Ipv6Scope::MULTICAST_SCOPE_ID_REALM_LOCAL => RealmLocal,
1386 Ipv6Scope::MULTICAST_SCOPE_ID_ADMIN_LOCAL => AdminLocal,
1387 Ipv6Scope::MULTICAST_SCOPE_ID_SITE_LOCAL => SiteLocal,
1388 6 => Unassigned(Scope6),
1389 7 => Unassigned(Scope7),
1390 Ipv6Scope::MULTICAST_SCOPE_ID_ORG_LOCAL => OrganizationLocal,
1391 9 => Unassigned(Scope9),
1392 0xA => Unassigned(ScopeA),
1393 0xB => Unassigned(ScopeB),
1394 0xC => Unassigned(ScopeC),
1395 0xD => Unassigned(ScopeD),
1396 Ipv6Scope::MULTICAST_SCOPE_ID_GLOBAL => Global,
1397 0xF => Reserved(ScopeF),
1398 _ => unreachable!(),
1399 }
1400 } else if self.is_link_local() {
1401 Ipv6Scope::LinkLocal
1402 } else if self.is_site_local() {
1403 Ipv6Scope::SiteLocal
1404 } else {
1405 Ipv6Scope::Global
1406 }
1407 }
1408}
1409
1410impl Scope for IpAddr<(), Ipv6Scope> {
1411 #[inline]
1412 fn can_have_zone(&self) -> bool {
1413 match self {
1414 IpAddr::V4(scope) => scope.can_have_zone(),
1415 IpAddr::V6(scope) => scope.can_have_zone(),
1416 }
1417 }
1418}
1419
1420impl ScopeableAddress for IpAddr {
1421 type Scope = IpAddr<(), Ipv6Scope>;
1422
1423 #[inline]
1424 fn scope(&self) -> IpAddr<(), Ipv6Scope> {
1425 match self {
1426 IpAddr::V4(_) => IpAddr::V4(()),
1427 IpAddr::V6(addr) => IpAddr::V6(addr.scope()),
1428 }
1429 }
1430}
1431
1432macro_rules! impl_from_witness {
1455 ($witness:ident, $witness_trait:ident) => {
1456 impl From<IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>> for $witness<IpAddr> {
1457 fn from(addr: IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>) -> $witness<IpAddr> {
1458 unsafe {
1459 Witness::new_unchecked(match addr {
1460 IpAddr::V4(addr) => IpAddr::V4(addr.get()),
1461 IpAddr::V6(addr) => IpAddr::V6(addr.get()),
1462 })
1463 }
1464 }
1465 }
1466 impl From<$witness<IpAddr>> for IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1467 fn from(addr: $witness<IpAddr>) -> IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1468 unsafe {
1469 match addr.get() {
1470 IpAddr::V4(addr) => IpAddr::V4(Witness::new_unchecked(addr)),
1471 IpAddr::V6(addr) => IpAddr::V6(Witness::new_unchecked(addr)),
1472 }
1473 }
1474 }
1475 }
1476 impl<A: IpAddress> From<$witness<A>> for $witness<IpAddr> {
1477 fn from(addr: $witness<A>) -> $witness<IpAddr> {
1478 unsafe { Witness::new_unchecked(addr.to_ip_addr()) }
1479 }
1480 }
1481 impl<A: IpAddress> From<$witness<A>> for IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1482 fn from(addr: $witness<A>) -> IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1483 let addr: $witness<IpAddr> = addr.into();
1484 addr.into()
1485 }
1486 }
1487 impl<A: Into<Ipv4Addr> + $witness_trait + Copy> From<$witness<A>> for Ipv4Addr {
1489 fn from(addr: $witness<A>) -> Ipv4Addr {
1490 let addr: A = addr.get();
1491 addr.into()
1492 }
1493 }
1494 impl<A: Into<Ipv6Addr> + $witness_trait + Copy> From<$witness<A>> for Ipv6Addr {
1495 fn from(addr: $witness<A>) -> Ipv6Addr {
1496 let addr: A = addr.get();
1497 addr.into()
1498 }
1499 }
1500 impl TryFrom<Ipv4Addr> for $witness<Ipv4Addr> {
1502 type Error = ();
1503 fn try_from(addr: Ipv4Addr) -> Result<$witness<Ipv4Addr>, ()> {
1504 Witness::new(addr).ok_or(())
1505 }
1506 }
1507 impl TryFrom<Ipv6Addr> for $witness<Ipv6Addr> {
1508 type Error = ();
1509 fn try_from(addr: Ipv6Addr) -> Result<$witness<Ipv6Addr>, ()> {
1510 Witness::new(addr).ok_or(())
1511 }
1512 }
1513 };
1514 ($witness:ident, $witness_trait:ident, $ipaddr:ident, $new_unchecked:expr) => {
1515 impl From<$witness<$ipaddr>> for $witness<IpAddr> {
1516 fn from(addr: $witness<$ipaddr>) -> $witness<IpAddr> {
1517 let addr: $ipaddr = addr.get();
1518 let addr: IpAddr = addr.into();
1519 #[allow(unused_unsafe)] unsafe {
1521 $new_unchecked(addr)
1522 }
1523 }
1524 }
1525 impl<A: Into<$ipaddr> + $witness_trait + Copy> From<$witness<A>> for $ipaddr {
1526 fn from(addr: $witness<A>) -> $ipaddr {
1527 let addr: A = addr.get();
1528 addr.into()
1529 }
1530 }
1531 impl TryFrom<$ipaddr> for $witness<$ipaddr> {
1532 type Error = ();
1533 fn try_from(addr: $ipaddr) -> Result<$witness<$ipaddr>, ()> {
1534 Witness::new(addr).ok_or(())
1535 }
1536 }
1537 };
1538}
1539
1540impl_from_witness!(SpecifiedAddr, SpecifiedAddress);
1541impl_from_witness!(MulticastAddr, MulticastAddress);
1542impl_from_witness!(LinkLocalAddr, LinkLocalAddress);
1543impl_from_witness!(NonMappedAddr, MappedAddress);
1544impl_from_witness!(UnicastAddr, UnicastAddress, Ipv6Addr, UnicastAddr::new_unchecked);
1547
1548#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1558pub enum Ipv4AddressClass {
1559 A,
1561 B,
1563 C,
1565 D,
1569 E,
1573}
1574
1575impl Ipv4AddressClass {
1576 pub const fn default_prefix_len(self) -> Option<u8> {
1579 match self {
1617 Ipv4AddressClass::A => Some(8),
1618 Ipv4AddressClass::B => Some(16),
1619 Ipv4AddressClass::C => Some(24),
1620 Ipv4AddressClass::D => None,
1621 Ipv4AddressClass::E => None,
1622 }
1623 }
1624}
1625
1626#[derive(
1649 Copy,
1650 Clone,
1651 Default,
1652 PartialEq,
1653 Eq,
1654 PartialOrd,
1655 Ord,
1656 Hash,
1657 KnownLayout,
1658 FromBytes,
1659 IntoBytes,
1660 Immutable,
1661 Unaligned,
1662)]
1663#[repr(transparent)]
1664pub struct Ipv4Addr([u8; 4]);
1665
1666impl Ipv4Addr {
1667 #[inline]
1669 pub const fn new(bytes: [u8; 4]) -> Self {
1670 Ipv4Addr(bytes)
1671 }
1672
1673 #[inline]
1675 pub const fn ipv4_bytes(self) -> [u8; 4] {
1676 self.0
1677 }
1678
1679 #[inline]
1684 pub fn is_limited_broadcast(self) -> bool {
1685 self == Ipv4::LIMITED_BROADCAST_ADDRESS.get()
1686 }
1687
1688 #[inline]
1693 pub fn is_class_e(self) -> bool {
1694 Ipv4::CLASS_E_SUBNET.contains(&self)
1695 }
1696
1697 #[inline]
1725 pub fn to_ipv6_compatible(self) -> Ipv6Addr {
1726 let Self([a, b, c, d]) = self;
1727 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
1728 }
1729
1730 #[inline]
1748 pub fn to_ipv6_mapped(self) -> SpecifiedAddr<Ipv6Addr> {
1749 let Self([a, b, c, d]) = self;
1750 SpecifiedAddr::new(Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d]))
1751 .unwrap()
1752 }
1753
1754 pub fn class(&self) -> Ipv4AddressClass {
1757 for (subnet, class) in [
1758 (Ipv4::CLASS_A_SUBNET, Ipv4AddressClass::A),
1759 (Ipv4::CLASS_B_SUBNET, Ipv4AddressClass::B),
1760 (Ipv4::CLASS_C_SUBNET, Ipv4AddressClass::C),
1761 (Ipv4::CLASS_D_SUBNET, Ipv4AddressClass::D),
1762 (Ipv4::CLASS_E_SUBNET, Ipv4AddressClass::E),
1763 ] {
1764 if subnet.contains(self) {
1765 return class;
1766 }
1767 }
1768
1769 unreachable!("{} should fit into a class", self)
1770 }
1771}
1772
1773impl sealed::Sealed for Ipv4Addr {}
1774
1775impl IpAddress for Ipv4Addr {
1776 const BYTES: u8 = 4;
1777
1778 type Version = Ipv4;
1779
1780 #[inline]
1781 fn mask(&self, bits: u8) -> Self {
1782 assert!(bits <= 32);
1783 let mask = u32::MAX.checked_shl((32 - bits).into()).unwrap_or(0);
1787 Ipv4Addr((u32::from_be_bytes(self.0) & mask).to_be_bytes())
1788 }
1789
1790 #[inline]
1791 fn bytes(&self) -> &[u8] {
1792 &self.0
1793 }
1794
1795 #[inline]
1796 fn to_ip_addr(&self) -> IpAddr {
1797 IpAddr::V4(*self)
1798 }
1799
1800 #[inline]
1801 fn common_prefix_len(&self, other: &Ipv4Addr) -> u8 {
1802 let me = u32::from_be_bytes(self.0);
1803 let other = u32::from_be_bytes(other.0);
1804 let same_bits = me ^ other;
1807 same_bits.leading_zeros() as u8
1808 }
1809
1810 #[inline]
1811 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool {
1812 !self.is_multicast()
1813 && !self.is_limited_broadcast()
1814 && (subnet.prefix() == 32
1818 || subnet.prefix() == 31
1819 || (*self != subnet.broadcast() && *self != subnet.network()))
1820 && self.is_specified()
1821 && !self.is_class_e()
1822 && subnet.contains(self)
1823 }
1824
1825 fn subnet_into_either(subnet: Subnet<Ipv4Addr>) -> SubnetEither {
1826 SubnetEither::V4(subnet)
1827 }
1828
1829 #[inline]
1830 fn array_into_ip_addr<const N: usize>(
1831 addrs: [Self; N],
1832 ) -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
1833 IpAddr::V4(addrs)
1834 }
1835}
1836
1837impl From<[u8; 4]> for Ipv4Addr {
1838 #[inline]
1839 fn from(bytes: [u8; 4]) -> Ipv4Addr {
1840 Ipv4Addr(bytes)
1841 }
1842}
1843
1844#[cfg(feature = "std")]
1845impl From<net::Ipv4Addr> for Ipv4Addr {
1846 #[inline]
1847 fn from(ip: net::Ipv4Addr) -> Ipv4Addr {
1848 Ipv4Addr::new(ip.octets())
1849 }
1850}
1851
1852#[cfg(feature = "std")]
1853impl From<Ipv4Addr> for net::Ipv4Addr {
1854 #[inline]
1855 fn from(ip: Ipv4Addr) -> net::Ipv4Addr {
1856 net::Ipv4Addr::from(ip.0)
1857 }
1858}
1859
1860impl Display for Ipv4Addr {
1861 #[inline]
1862 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1863 write!(f, "{}.{}.{}.{}", self.0[0], self.0[1], self.0[2], self.0[3])
1864 }
1865}
1866
1867impl Debug for Ipv4Addr {
1868 #[inline]
1869 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1870 Display::fmt(self, f)
1871 }
1872}
1873
1874#[allow(missing_docs)]
1881#[derive(Copy, Clone, Eq, PartialEq)]
1882pub enum Ipv4SourceAddr {
1883 Specified(NonMulticastAddr<SpecifiedAddr<Ipv4Addr>>),
1884 Unspecified,
1885}
1886
1887impl crate::sealed::Sealed for Ipv4SourceAddr {}
1888
1889impl Ipv4SourceAddr {
1890 #[inline]
1895 pub fn new(addr: Ipv4Addr) -> Option<Ipv4SourceAddr> {
1896 match SpecifiedAddr::new(addr) {
1897 Some(addr) => NonMulticastAddr::new(addr).map(Ipv4SourceAddr::Specified),
1898 None => Some(Ipv4SourceAddr::Unspecified),
1899 }
1900 }
1901}
1902
1903impl Witness<Ipv4Addr> for Ipv4SourceAddr {
1904 #[inline]
1905 fn new(addr: Ipv4Addr) -> Option<Ipv4SourceAddr> {
1906 Ipv4SourceAddr::new(addr)
1907 }
1908
1909 #[inline]
1910 unsafe fn new_unchecked(addr: Ipv4Addr) -> Ipv4SourceAddr {
1911 Ipv4SourceAddr::new(addr).unwrap()
1912 }
1913
1914 #[inline]
1915 fn into_addr(self) -> Ipv4Addr {
1916 match self {
1917 Ipv4SourceAddr::Specified(addr) => **addr,
1918 Ipv4SourceAddr::Unspecified => Ipv4::UNSPECIFIED_ADDRESS,
1919 }
1920 }
1921}
1922
1923impl From<Ipv4SourceAddr> for Ipv4Addr {
1924 fn from(addr: Ipv4SourceAddr) -> Ipv4Addr {
1925 addr.get()
1926 }
1927}
1928
1929impl AsRef<Ipv4Addr> for Ipv4SourceAddr {
1930 fn as_ref(&self) -> &Ipv4Addr {
1931 match self {
1932 Ipv4SourceAddr::Specified(addr) => addr,
1933 Ipv4SourceAddr::Unspecified => &Ipv4::UNSPECIFIED_ADDRESS,
1934 }
1935 }
1936}
1937
1938impl Deref for Ipv4SourceAddr {
1939 type Target = Ipv4Addr;
1940
1941 fn deref(&self) -> &Ipv4Addr {
1942 self.as_ref()
1943 }
1944}
1945
1946impl Display for Ipv4SourceAddr {
1947 #[inline]
1948 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1949 write!(f, "{}", self.get())
1950 }
1951}
1952
1953impl Debug for Ipv4SourceAddr {
1954 #[inline]
1955 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1956 Display::fmt(self, f)
1957 }
1958}
1959
1960#[derive(
1995 Copy,
1996 Clone,
1997 Default,
1998 PartialEq,
1999 Eq,
2000 PartialOrd,
2001 Ord,
2002 Hash,
2003 KnownLayout,
2004 FromBytes,
2005 IntoBytes,
2006 Immutable,
2007 Unaligned,
2008)]
2009#[repr(transparent)]
2010pub struct Ipv6Addr([u8; 16]);
2011
2012impl Ipv6Addr {
2013 #[inline]
2015 pub const fn new(segments: [u16; 8]) -> Ipv6Addr {
2016 #![allow(clippy::many_single_char_names)]
2017 let [a, b, c, d, e, f, g, h] = segments;
2018 let [aa, ab] = a.to_be_bytes();
2019 let [ba, bb] = b.to_be_bytes();
2020 let [ca, cb] = c.to_be_bytes();
2021 let [da, db] = d.to_be_bytes();
2022 let [ea, eb] = e.to_be_bytes();
2023 let [fa, fb] = f.to_be_bytes();
2024 let [ga, gb] = g.to_be_bytes();
2025 let [ha, hb] = h.to_be_bytes();
2026 Ipv6Addr([aa, ab, ba, bb, ca, cb, da, db, ea, eb, fa, fb, ga, gb, ha, hb])
2027 }
2028
2029 #[inline]
2031 pub const fn from_bytes(bytes: [u8; 16]) -> Ipv6Addr {
2032 Ipv6Addr(bytes)
2033 }
2034
2035 #[inline]
2037 pub const fn ipv6_bytes(&self) -> [u8; 16] {
2038 self.0
2039 }
2040
2041 #[inline]
2043 pub fn segments(&self) -> [u16; 8] {
2044 #![allow(clippy::many_single_char_names)]
2045 let [a, b, c, d, e, f, g, h]: [zerocopy::network_endian::U16; 8] =
2046 zerocopy::transmute!(self.ipv6_bytes());
2047 [a.into(), b.into(), c.into(), d.into(), e.into(), f.into(), g.into(), h.into()]
2048 }
2049
2050 #[inline]
2055 pub const fn to_solicited_node_address(&self) -> MulticastAddr<Ipv6Addr> {
2056 unsafe {
2064 MulticastAddr::new_unchecked(Ipv6Addr::from_bytes([
2065 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xff, self.0[13], self.0[14],
2066 self.0[15],
2067 ]))
2068 }
2069 }
2070
2071 #[inline]
2078 pub fn is_valid_unicast(&self) -> bool {
2079 !(self.is_loopback() || !self.is_specified() || self.is_multicast())
2080 }
2081
2082 #[inline]
2089 pub fn is_site_local(&self) -> bool {
2090 Ipv6::SITE_LOCAL_UNICAST_SUBNET.contains(self)
2091 }
2092
2093 #[inline]
2098 pub fn is_unicast_link_local(&self) -> bool {
2099 self.is_unicast_in_subnet(&Ipv6::LINK_LOCAL_UNICAST_SUBNET)
2100 }
2101
2102 pub fn to_ipv4_compatible(&self) -> Option<Ipv4Addr> {
2132 if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] = self.0 {
2133 Some(Ipv4Addr::new([a, b, c, d]))
2134 } else {
2135 None
2136 }
2137 }
2138
2139 pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
2159 if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] = self.0 {
2160 Some(Ipv4Addr::new([a, b, c, d]))
2161 } else {
2162 None
2163 }
2164 }
2165}
2166
2167impl sealed::Sealed for Ipv6Addr {}
2168
2169impl From<Ipv4Addr> for Ipv6Addr {
2172 fn from(addr: Ipv4Addr) -> Ipv6Addr {
2173 *addr.to_ipv6_mapped()
2174 }
2175}
2176
2177impl IpAddress for Ipv6Addr {
2178 const BYTES: u8 = 16;
2179
2180 type Version = Ipv6;
2181
2182 #[inline]
2183 fn mask(&self, bits: u8) -> Ipv6Addr {
2184 assert!(bits <= 128);
2185 let mask = u128::MAX.checked_shl((128 - bits).into()).unwrap_or(0);
2189 Ipv6Addr((u128::from_be_bytes(self.0) & mask).to_be_bytes())
2190 }
2191
2192 #[inline]
2193 fn bytes(&self) -> &[u8] {
2194 &self.0
2195 }
2196
2197 #[inline]
2198 fn to_ip_addr(&self) -> IpAddr {
2199 IpAddr::V6(*self)
2200 }
2201
2202 #[inline]
2203 fn common_prefix_len(&self, other: &Ipv6Addr) -> u8 {
2204 let me = u128::from_be_bytes(self.0);
2205 let other = u128::from_be_bytes(other.0);
2206 let same_bits = me ^ other;
2209 same_bits.leading_zeros() as u8
2210 }
2211
2212 #[inline]
2213 fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool {
2214 !self.is_multicast() && self.is_specified() && subnet.contains(self)
2215 }
2216
2217 fn subnet_into_either(subnet: Subnet<Ipv6Addr>) -> SubnetEither {
2218 SubnetEither::V6(subnet)
2219 }
2220
2221 #[inline]
2222 fn array_into_ip_addr<const N: usize>(
2223 addrs: [Self; N],
2224 ) -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
2225 IpAddr::V6(addrs)
2226 }
2227}
2228
2229impl UnicastAddress for Ipv6Addr {
2230 #[inline]
2235 fn is_unicast(&self) -> bool {
2236 !self.is_multicast() && self.is_specified()
2237 }
2238}
2239
2240impl From<[u8; 16]> for Ipv6Addr {
2241 #[inline]
2242 fn from(bytes: [u8; 16]) -> Ipv6Addr {
2243 Ipv6Addr::from_bytes(bytes)
2244 }
2245}
2246
2247#[cfg(feature = "std")]
2248impl From<net::Ipv6Addr> for Ipv6Addr {
2249 #[inline]
2250 fn from(addr: net::Ipv6Addr) -> Ipv6Addr {
2251 Ipv6Addr::from_bytes(addr.octets())
2252 }
2253}
2254
2255#[cfg(feature = "std")]
2256impl From<Ipv6Addr> for net::Ipv6Addr {
2257 #[inline]
2258 fn from(addr: Ipv6Addr) -> net::Ipv6Addr {
2259 net::Ipv6Addr::from(addr.ipv6_bytes())
2260 }
2261}
2262
2263impl Display for Ipv6Addr {
2264 #[inline]
2273 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2274 fn fmt_inner<W: fmt::Write>(addr: &Ipv6Addr, w: &mut W) -> Result<(), fmt::Error> {
2279 if !addr.is_specified() {
2283 write!(w, "::")
2284 } else if addr.is_loopback() {
2285 write!(w, "::1")
2286 } else if let Some(v4) = addr.to_ipv4_mapped() {
2287 write!(w, "::ffff:{}", v4)
2288 } else {
2289 let segments = addr.segments();
2290
2291 let longest_zero_span = {
2292 let mut longest_zero_span = 0..0;
2293 let mut current_zero_span = 0..0;
2294 for (i, seg) in segments.iter().enumerate() {
2295 if *seg == 0 {
2296 current_zero_span.end = i + 1;
2297 if current_zero_span.len() > longest_zero_span.len() {
2298 longest_zero_span = current_zero_span.clone();
2299 }
2300 } else {
2301 let next_idx = i + 1;
2302 current_zero_span = next_idx..next_idx;
2303 }
2304 }
2305 longest_zero_span
2306 };
2307
2308 let write_slice = |w: &mut W, slice: &[u16]| {
2309 if let [head, tail @ ..] = slice {
2310 write!(w, "{:x}", head)?;
2311 for seg in tail {
2312 write!(w, ":{:x}", seg)?;
2313 }
2314 }
2315 Ok(())
2316 };
2317
2318 if longest_zero_span.len() > 1 {
2335 write_slice(w, &segments[..longest_zero_span.start])?;
2336 w.write_str("::")?;
2337 write_slice(w, &segments[longest_zero_span.end..])
2338 } else {
2339 write_slice(w, &segments)
2340 }
2341 }
2342 }
2343
2344 if f.precision().is_none() && f.width().is_none() {
2345 fmt_inner(self, f)
2348 } else {
2349 struct ByteSlice<'a>(&'a mut [u8]);
2356
2357 impl<'a> fmt::Write for ByteSlice<'a> {
2358 fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
2359 let from = s.as_bytes();
2360
2361 if from.len() > self.0.len() {
2362 return Err(fmt::Error);
2363 }
2364
2365 let to = mem::replace(&mut self.0, &mut [][..]);
2371 let (to, remaining) = to.split_at_mut(from.len());
2372 to.copy_from_slice(from);
2373
2374 self.0 = remaining;
2375 Ok(())
2376 }
2377 }
2378
2379 const MAX_DISPLAY_LEN: usize = (4 * 8) + 7;
2383 let mut scratch = [0u8; MAX_DISPLAY_LEN];
2384 let mut scratch_slice = ByteSlice(&mut scratch[..]);
2385 fmt_inner(self, &mut scratch_slice)
2392 .expect("<Ipv6Addr as Display>::fmt: fmt_inner should have succeeded because the scratch buffer was long enough");
2393 let unwritten = scratch_slice.0.len();
2394 let len = MAX_DISPLAY_LEN - unwritten;
2395 let str = core::str::from_utf8(&scratch[..len])
2397 .expect("<Ipv6Addr as Display>::fmt: scratch buffer should contain valid UTF-8");
2398 f.pad(str)
2399 }
2400 }
2401}
2402
2403impl Debug for Ipv6Addr {
2404 #[inline]
2405 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2406 Display::fmt(self, f)
2407 }
2408}
2409
2410#[allow(missing_docs)]
2417#[derive(Copy, Clone, Eq, PartialEq)]
2418pub enum Ipv6SourceAddr {
2419 Unicast(NonMappedAddr<UnicastAddr<Ipv6Addr>>),
2420 Unspecified,
2421}
2422
2423impl crate::sealed::Sealed for Ipv6SourceAddr {}
2424
2425impl Ipv6SourceAddr {
2426 #[inline]
2431 pub fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2432 if let Some(addr) = UnicastAddr::new(addr) {
2433 NonMappedAddr::new(addr).map(Ipv6SourceAddr::Unicast)
2434 } else if !addr.is_specified() {
2435 Some(Ipv6SourceAddr::Unspecified)
2436 } else {
2437 None
2438 }
2439 }
2440}
2441
2442impl Witness<Ipv6Addr> for Ipv6SourceAddr {
2443 #[inline]
2444 fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2445 Ipv6SourceAddr::new(addr)
2446 }
2447
2448 #[inline]
2449 unsafe fn new_unchecked(addr: Ipv6Addr) -> Ipv6SourceAddr {
2450 Ipv6SourceAddr::new(addr).unwrap()
2451 }
2452
2453 #[inline]
2454 fn into_addr(self) -> Ipv6Addr {
2455 match self {
2456 Ipv6SourceAddr::Unicast(addr) => **addr,
2457 Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2458 }
2459 }
2460}
2461
2462impl SpecifiedAddress for Ipv6SourceAddr {
2463 fn is_specified(&self) -> bool {
2464 self != &Ipv6SourceAddr::Unspecified
2465 }
2466}
2467
2468impl UnicastAddress for Ipv6SourceAddr {
2469 fn is_unicast(&self) -> bool {
2470 matches!(self, Ipv6SourceAddr::Unicast(_))
2471 }
2472}
2473
2474impl LinkLocalAddress for Ipv6SourceAddr {
2475 fn is_link_local(&self) -> bool {
2476 let addr: Ipv6Addr = self.into();
2477 addr.is_link_local()
2478 }
2479}
2480
2481impl MappedAddress for Ipv6SourceAddr {
2482 fn is_non_mapped(&self) -> bool {
2483 let addr: Ipv6Addr = self.into();
2484 addr.is_non_mapped()
2485 }
2486}
2487
2488impl From<Ipv6SourceAddr> for Ipv6Addr {
2489 fn from(addr: Ipv6SourceAddr) -> Ipv6Addr {
2490 addr.get()
2491 }
2492}
2493
2494impl From<&'_ Ipv6SourceAddr> for Ipv6Addr {
2495 fn from(addr: &Ipv6SourceAddr) -> Ipv6Addr {
2496 match addr {
2497 Ipv6SourceAddr::Unicast(addr) => addr.get(),
2498 Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2499 }
2500 }
2501}
2502
2503impl TryFrom<Ipv6Addr> for Ipv6SourceAddr {
2504 type Error = ();
2505 fn try_from(addr: Ipv6Addr) -> Result<Ipv6SourceAddr, ()> {
2506 Ipv6SourceAddr::new(addr).ok_or(())
2507 }
2508}
2509
2510impl AsRef<Ipv6Addr> for Ipv6SourceAddr {
2511 fn as_ref(&self) -> &Ipv6Addr {
2512 match self {
2513 Ipv6SourceAddr::Unicast(addr) => addr,
2514 Ipv6SourceAddr::Unspecified => &Ipv6::UNSPECIFIED_ADDRESS,
2515 }
2516 }
2517}
2518
2519impl Deref for Ipv6SourceAddr {
2520 type Target = Ipv6Addr;
2521
2522 fn deref(&self) -> &Ipv6Addr {
2523 self.as_ref()
2524 }
2525}
2526
2527impl Display for Ipv6SourceAddr {
2528 #[inline]
2529 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2530 match self {
2531 Ipv6SourceAddr::Unicast(addr) => write!(f, "{}", addr),
2532 Ipv6SourceAddr::Unspecified => write!(f, "::"),
2533 }
2534 }
2535}
2536
2537impl Debug for Ipv6SourceAddr {
2538 #[inline]
2539 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2540 Display::fmt(self, f)
2541 }
2542}
2543
2544#[allow(missing_docs)]
2552#[derive(Copy, Clone, Eq, PartialEq)]
2553pub enum UnicastOrMulticastIpv6Addr {
2554 Unicast(UnicastAddr<Ipv6Addr>),
2555 Multicast(MulticastAddr<Ipv6Addr>),
2556}
2557
2558impl UnicastOrMulticastIpv6Addr {
2559 pub fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2563 SpecifiedAddr::new(addr).map(UnicastOrMulticastIpv6Addr::from_specified)
2564 }
2565
2566 pub fn from_specified(addr: SpecifiedAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2568 if addr.is_unicast() {
2569 UnicastOrMulticastIpv6Addr::Unicast(UnicastAddr(addr.get()))
2570 } else {
2571 UnicastOrMulticastIpv6Addr::Multicast(MulticastAddr(addr.get()))
2572 }
2573 }
2574}
2575
2576impl crate::sealed::Sealed for UnicastOrMulticastIpv6Addr {}
2577
2578impl Witness<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2579 #[inline]
2580 fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2581 UnicastOrMulticastIpv6Addr::new(addr)
2582 }
2583
2584 #[inline]
2585 unsafe fn new_unchecked(addr: Ipv6Addr) -> UnicastOrMulticastIpv6Addr {
2586 UnicastOrMulticastIpv6Addr::new(addr).unwrap()
2587 }
2588
2589 #[inline]
2590 fn into_addr(self) -> Ipv6Addr {
2591 match self {
2592 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.get(),
2593 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.get(),
2594 }
2595 }
2596}
2597
2598impl UnicastAddress for UnicastOrMulticastIpv6Addr {
2599 fn is_unicast(&self) -> bool {
2600 matches!(self, UnicastOrMulticastIpv6Addr::Unicast(_))
2601 }
2602}
2603
2604impl MulticastAddress for UnicastOrMulticastIpv6Addr {
2605 fn is_multicast(&self) -> bool {
2606 matches!(self, UnicastOrMulticastIpv6Addr::Multicast(_))
2607 }
2608}
2609
2610impl LinkLocalAddress for UnicastOrMulticastIpv6Addr {
2611 fn is_link_local(&self) -> bool {
2612 match self {
2613 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_link_local(),
2614 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_link_local(),
2615 }
2616 }
2617}
2618
2619impl MappedAddress for UnicastOrMulticastIpv6Addr {
2620 fn is_non_mapped(&self) -> bool {
2621 match self {
2622 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_non_mapped(),
2623 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_non_mapped(),
2624 }
2625 }
2626}
2627
2628impl From<UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2629 fn from(addr: UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2630 addr.get()
2631 }
2632}
2633
2634impl From<&'_ UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2635 fn from(addr: &UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2636 addr.get()
2637 }
2638}
2639
2640impl From<UnicastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2641 fn from(addr: UnicastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2642 UnicastOrMulticastIpv6Addr::Unicast(addr)
2643 }
2644}
2645
2646impl From<MulticastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2647 fn from(addr: MulticastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2648 UnicastOrMulticastIpv6Addr::Multicast(addr)
2649 }
2650}
2651
2652impl TryFrom<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2653 type Error = ();
2654 fn try_from(addr: Ipv6Addr) -> Result<UnicastOrMulticastIpv6Addr, ()> {
2655 UnicastOrMulticastIpv6Addr::new(addr).ok_or(())
2656 }
2657}
2658
2659impl AsRef<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2660 fn as_ref(&self) -> &Ipv6Addr {
2661 match self {
2662 UnicastOrMulticastIpv6Addr::Unicast(addr) => addr,
2663 UnicastOrMulticastIpv6Addr::Multicast(addr) => addr,
2664 }
2665 }
2666}
2667
2668impl Deref for UnicastOrMulticastIpv6Addr {
2669 type Target = Ipv6Addr;
2670
2671 fn deref(&self) -> &Ipv6Addr {
2672 self.as_ref()
2673 }
2674}
2675
2676impl Display for UnicastOrMulticastIpv6Addr {
2677 #[inline]
2678 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2679 match self {
2680 UnicastOrMulticastIpv6Addr::Unicast(addr) => write!(f, "{}", addr),
2681 UnicastOrMulticastIpv6Addr::Multicast(addr) => write!(f, "{}", addr),
2682 }
2683 }
2684}
2685
2686impl Debug for UnicastOrMulticastIpv6Addr {
2687 #[inline]
2688 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2689 Display::fmt(self, f)
2690 }
2691}
2692
2693#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2695pub enum SubnetError {
2696 PrefixTooLong,
2699 HostBitsSet,
2702}
2703
2704#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2707pub struct PrefixTooLongError;
2708
2709#[derive(Copy, Clone, Eq, PartialEq, Hash)]
2713pub struct Subnet<A> {
2714 network: A,
2716 prefix: u8,
2717}
2718
2719impl<A: core::cmp::Ord> core::cmp::PartialOrd for Subnet<A> {
2720 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
2721 Some(self.cmp(other))
2722 }
2723}
2724
2725impl<A: core::cmp::Ord> core::cmp::Ord for Subnet<A> {
2727 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
2728 let Self { network, prefix } = self;
2729 let Self { network: other_network, prefix: other_prefix } = other;
2730 match prefix.cmp(other_prefix) {
2731 core::cmp::Ordering::Equal => network.cmp(other_network),
2732 ord => ord,
2733 }
2734 }
2735}
2736
2737impl<A> Subnet<A> {
2738 #[inline]
2748 pub const unsafe fn new_unchecked(network: A, prefix: u8) -> Subnet<A> {
2749 Subnet { network, prefix }
2750 }
2751}
2752
2753impl<A: IpAddress> Subnet<A> {
2754 #[inline]
2761 pub fn new(network: A, prefix: u8) -> Result<Subnet<A>, SubnetError> {
2762 if prefix > A::BYTES * 8 {
2763 return Err(SubnetError::PrefixTooLong);
2764 }
2765 if network != network.mask(prefix) {
2768 return Err(SubnetError::HostBitsSet);
2769 }
2770 Ok(Subnet { network, prefix })
2771 }
2772
2773 #[inline]
2779 pub fn from_host(host: A, prefix: u8) -> Result<Subnet<A>, PrefixTooLongError> {
2780 if prefix > A::BYTES * 8 {
2781 return Err(PrefixTooLongError);
2782 }
2783 let network = host.mask(prefix);
2784 Ok(Subnet { network, prefix })
2785 }
2786
2787 #[inline]
2791 pub fn network(&self) -> A {
2792 self.network
2793 }
2794
2795 #[inline]
2797 pub fn prefix(&self) -> u8 {
2798 self.prefix
2799 }
2800
2801 #[inline]
2807 pub fn contains(&self, addr: &A) -> bool {
2808 self.network == addr.mask(self.prefix)
2809 }
2810}
2811
2812impl Subnet<Ipv4Addr> {
2813 #[inline]
2821 pub fn broadcast(self) -> Ipv4Addr {
2822 if self.prefix == 32 {
2823 self.network
2825 } else {
2826 let mask = <u32>::max_value() >> self.prefix;
2827 Ipv4Addr::new((u32::from_be_bytes(self.network.0) | mask).to_be_bytes())
2828 }
2829 }
2830}
2831
2832impl<A: IpAddress> Display for Subnet<A> {
2833 #[inline]
2834 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2835 write!(f, "{}/{}", self.network, self.prefix)
2836 }
2837}
2838
2839impl<A: IpAddress> Debug for Subnet<A> {
2840 #[inline]
2841 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2842 write!(f, "{}/{}", self.network, self.prefix)
2843 }
2844}
2845
2846impl<A, I: Ip> GenericOverIp<I> for Subnet<A> {
2847 type Type = Subnet<I::Addr>;
2848}
2849
2850#[allow(missing_docs)]
2856#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2857pub enum SubnetEither {
2858 V4(Subnet<Ipv4Addr>),
2859 V6(Subnet<Ipv6Addr>),
2860}
2861
2862impl SubnetEither {
2863 #[inline]
2870 pub fn new(network: IpAddr, prefix: u8) -> Result<SubnetEither, SubnetError> {
2871 Ok(match network {
2872 IpAddr::V4(network) => SubnetEither::V4(Subnet::new(network, prefix)?),
2873 IpAddr::V6(network) => SubnetEither::V6(Subnet::new(network, prefix)?),
2874 })
2875 }
2876
2877 #[inline]
2883 pub fn from_host(host: IpAddr, prefix: u8) -> Result<SubnetEither, PrefixTooLongError> {
2884 Ok(match host {
2885 IpAddr::V4(host) => SubnetEither::V4(Subnet::from_host(host, prefix)?),
2886 IpAddr::V6(host) => SubnetEither::V6(Subnet::from_host(host, prefix)?),
2887 })
2888 }
2889
2890 #[inline]
2892 pub fn net_prefix(&self) -> (IpAddr, u8) {
2893 match self {
2894 SubnetEither::V4(v4) => (v4.network.into(), v4.prefix),
2895 SubnetEither::V6(v6) => (v6.network.into(), v6.prefix),
2896 }
2897 }
2898}
2899
2900impl<A: IpAddress> From<Subnet<A>> for SubnetEither {
2901 fn from(subnet: Subnet<A>) -> SubnetEither {
2902 A::subnet_into_either(subnet)
2903 }
2904}
2905
2906#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2908pub enum AddrSubnetError {
2909 PrefixTooLong,
2912 NotUnicastInSubnet,
2915 InvalidWitness,
2917}
2918
2919#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2930pub struct AddrSubnet<S: IpAddress, A: Witness<S> + Copy = SpecifiedAddr<S>> {
2931 addr: A,
2935 subnet: Subnet<S>,
2936}
2937
2938impl<S: IpAddress, A: Witness<S> + Copy> AddrSubnet<S, A> {
2939 #[inline]
2947 pub fn new(addr: S, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2948 AddrSubnet::from_witness(A::new(addr).ok_or(AddrSubnetError::InvalidWitness)?, prefix)
2949 }
2950
2951 #[inline]
2962 pub unsafe fn new_unchecked(addr: S, prefix: u8) -> Self {
2963 let (subnet, addr) =
2964 unsafe { (Subnet::new_unchecked(addr.mask(prefix), prefix), A::new_unchecked(addr)) };
2965 AddrSubnet { addr, subnet }
2966 }
2967
2968 pub fn from_witness(addr: A, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2977 if prefix > S::BYTES * 8 {
2978 return Err(AddrSubnetError::PrefixTooLong);
2979 }
2980 let subnet = Subnet { network: addr.as_ref().mask(prefix), prefix };
2981 if !addr.as_ref().is_unicast_in_subnet(&subnet) {
2982 return Err(AddrSubnetError::NotUnicastInSubnet);
2983 }
2984 Ok(AddrSubnet { addr, subnet })
2985 }
2986
2987 #[inline]
2989 pub fn subnet(&self) -> Subnet<S> {
2990 self.subnet
2991 }
2992
2993 #[inline]
2995 pub fn addr(&self) -> A {
2996 self.addr
2997 }
2998
2999 #[inline]
3001 pub fn addr_subnet(self) -> (A, Subnet<S>) {
3002 (self.addr, self.subnet)
3003 }
3004
3005 #[inline]
3007 pub fn to_witness<B: Witness<S> + Copy>(&self) -> AddrSubnet<S, B>
3008 where
3009 A: Into<B>,
3010 {
3011 AddrSubnet { addr: self.addr.into(), subnet: self.subnet }
3012 }
3013
3014 #[inline]
3016 pub fn add_witness<B: Witness<A> + Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
3017 let addr = B::new(self.addr)?;
3018 Some(AddrSubnet { addr, subnet: self.subnet })
3019 }
3020
3021 #[inline]
3023 pub fn replace_witness<B: Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
3024 let addr = B::new(self.addr.get())?;
3025 Some(AddrSubnet { addr, subnet: self.subnet })
3026 }
3027}
3028
3029impl<S: IpAddress, A: Witness<S> + Copy + Display> Display for AddrSubnet<S, A> {
3030 #[inline]
3031 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
3032 write!(f, "{}/{}", self.addr, self.subnet.prefix)
3033 }
3034}
3035
3036impl<A: Witness<Ipv6Addr> + Copy> AddrSubnet<Ipv6Addr, A> {
3037 pub fn ipv6_unicast_addr(&self) -> UnicastAddr<Ipv6Addr> {
3043 unsafe { UnicastAddr::new_unchecked(self.addr.get()) }
3044 }
3045
3046 pub fn to_unicast(&self) -> AddrSubnet<Ipv6Addr, UnicastAddr<Ipv6Addr>> {
3052 let AddrSubnet { addr, subnet } = *self;
3053 let addr = unsafe { UnicastAddr::new_unchecked(addr.get()) };
3054 AddrSubnet { addr, subnet }
3055 }
3056}
3057
3058#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, GenericOverIp)]
3060#[generic_over_ip(I, Ip)]
3061pub struct PrefixLength<I: Ip> {
3062 inner: u8,
3064 _ip: IpVersionMarker<I>,
3065}
3066
3067impl<I: Ip> PrefixLength<I> {
3068 pub const fn get(self) -> u8 {
3073 let Self { inner, _ip } = self;
3074 inner
3075 }
3076
3077 pub fn get_mask(self) -> I::Addr {
3079 I::map_ip(
3080 self,
3081 |prefix_len| Ipv4::LIMITED_BROADCAST_ADDRESS.mask(prefix_len.get()),
3082 |prefix_len| Ipv6Addr([u8::MAX; 16]).mask(prefix_len.get()),
3083 )
3084 }
3085
3086 pub const unsafe fn new_unchecked(prefix_length: u8) -> Self {
3093 Self { inner: prefix_length, _ip: I::VERSION_MARKER }
3094 }
3095
3096 pub const fn new(prefix_length: u8) -> Result<Self, PrefixTooLongError> {
3101 if prefix_length > I::Addr::BYTES * 8 {
3102 return Err(PrefixTooLongError);
3103 }
3104 Ok(Self { inner: prefix_length, _ip: I::VERSION_MARKER })
3105 }
3106
3107 pub fn try_from_subnet_mask(subnet_mask: I::Addr) -> Result<Self, NotSubnetMaskError> {
3112 let IpInvariant((count_ones, leading_ones)) = I::map_ip(
3113 subnet_mask,
3114 |subnet_mask| {
3115 let number = u32::from_be_bytes(subnet_mask.ipv4_bytes());
3116 IpInvariant((number.count_ones(), number.leading_ones()))
3117 },
3118 |subnet_mask| {
3119 let number = u128::from_be_bytes(subnet_mask.ipv6_bytes());
3120 IpInvariant((number.count_ones(), number.leading_ones()))
3121 },
3122 );
3123
3124 if leading_ones != count_ones {
3125 return Err(NotSubnetMaskError);
3126 }
3127
3128 Ok(Self {
3129 inner: u8::try_from(leading_ones)
3130 .expect("the number of bits in an IP address fits in u8"),
3131 _ip: IpVersionMarker::default(),
3132 })
3133 }
3134}
3135
3136impl<I: Ip> From<PrefixLength<I>> for u8 {
3137 fn from(value: PrefixLength<I>) -> Self {
3138 value.get()
3139 }
3140}
3141
3142#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3145pub struct NotSubnetMaskError;
3146
3147pub trait IpAddressWitness<A: IpAddress>: Witness<A> {
3160 type IpAddrWitness: IpAddrWitness + From<Self>;
3165}
3166
3167macro_rules! impl_ip_address_witness {
3168 ($witness:ident) => {
3169 impl<A: IpAddress> IpAddressWitness<A> for $witness<A> {
3170 type IpAddrWitness = $witness<IpAddr>;
3171 }
3172 };
3173}
3174
3175impl_ip_address_witness!(SpecifiedAddr);
3176impl_ip_address_witness!(MulticastAddr);
3177impl_ip_address_witness!(LinkLocalAddr);
3178
3179pub trait IpAddrWitness: Witness<IpAddr> + Into<IpAddr<Self::V4, Self::V6>> + Copy {
3193 type V4: Witness<Ipv4Addr> + Into<Self> + Copy;
3198
3199 type V6: Witness<Ipv6Addr> + Into<Self> + Copy;
3204
3205 fn from_v4(addr: Self::V4) -> Self {
3210 addr.into()
3211 }
3212
3213 fn from_v6(addr: Self::V6) -> Self {
3215 addr.into()
3216 }
3217}
3218
3219macro_rules! impl_ip_addr_witness {
3220 ($witness:ident) => {
3221 impl IpAddrWitness for $witness<IpAddr> {
3222 type V4 = $witness<Ipv4Addr>;
3223 type V6 = $witness<Ipv6Addr>;
3224 }
3225 };
3226}
3227
3228impl_ip_addr_witness!(SpecifiedAddr);
3229impl_ip_addr_witness!(MulticastAddr);
3230impl_ip_addr_witness!(LinkLocalAddr);
3231
3232#[allow(missing_docs)]
3239#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
3240pub enum AddrSubnetEither<A: IpAddrWitness = SpecifiedAddr<IpAddr>> {
3241 V4(AddrSubnet<Ipv4Addr, A::V4>),
3242 V6(AddrSubnet<Ipv6Addr, A::V6>),
3243}
3244
3245impl<A: IpAddrWitness> AddrSubnetEither<A> {
3246 #[inline]
3252 pub fn new(addr: IpAddr, prefix: u8) -> Result<AddrSubnetEither<A>, AddrSubnetError> {
3253 Ok(match addr {
3254 IpAddr::V4(addr) => AddrSubnetEither::V4(AddrSubnet::new(addr, prefix)?),
3255 IpAddr::V6(addr) => AddrSubnetEither::V6(AddrSubnet::new(addr, prefix)?),
3256 })
3257 }
3258
3259 #[inline]
3269 pub unsafe fn new_unchecked(addr: IpAddr, prefix: u8) -> Self {
3270 match addr {
3271 IpAddr::V4(addr) => {
3272 AddrSubnetEither::V4(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3273 }
3274 IpAddr::V6(addr) => {
3275 AddrSubnetEither::V6(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3276 }
3277 }
3278 }
3279
3280 pub fn addr(&self) -> A {
3282 match self {
3283 AddrSubnetEither::V4(v4) => v4.addr.into(),
3284 AddrSubnetEither::V6(v6) => v6.addr.into(),
3285 }
3286 }
3287
3288 #[inline]
3290 pub fn addr_prefix(&self) -> (A, u8) {
3291 match self {
3292 AddrSubnetEither::V4(v4) => (v4.addr.into(), v4.subnet.prefix),
3293 AddrSubnetEither::V6(v6) => (v6.addr.into(), v6.subnet.prefix),
3294 }
3295 }
3296
3297 #[inline]
3299 pub fn addr_subnet(&self) -> (A, SubnetEither) {
3300 match self {
3301 AddrSubnetEither::V4(v4) => (v4.addr.into(), SubnetEither::V4(v4.subnet)),
3302 AddrSubnetEither::V6(v6) => (v6.addr.into(), SubnetEither::V6(v6.subnet)),
3303 }
3304 }
3305}
3306
3307impl<S: IpAddress, A: IpAddressWitness<S> + Copy> From<AddrSubnet<S, A>>
3308 for AddrSubnetEither<A::IpAddrWitness>
3309{
3310 #[inline]
3311 fn from(addr_sub: AddrSubnet<S, A>) -> AddrSubnetEither<A::IpAddrWitness> {
3312 let (addr, sub) = addr_sub.addr_subnet();
3313 AddrSubnetEither::new(addr.get().to_ip_addr(), sub.prefix()).unwrap()
3324 }
3325}
3326
3327impl<A> Display for AddrSubnetEither<A>
3328where
3329 A: IpAddrWitness,
3330 A::V4: Display,
3331 A::V6: Display,
3332{
3333 #[inline]
3334 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
3335 match self {
3336 Self::V4(a) => write!(f, "{}", a),
3337 Self::V6(a) => write!(f, "{}", a),
3338 }
3339 }
3340}
3341
3342pub trait GenericOverIp<NewIp: Ip> {
3361 type Type;
3364}
3365
3366pub struct IpInvariant<T>(pub T);
3371
3372impl<T> IpInvariant<T> {
3373 pub fn into_inner(self) -> T {
3375 self.0
3376 }
3377}
3378
3379impl<I: Ip, T> GenericOverIp<I> for IpInvariant<T> {
3380 type Type = Self;
3381}
3382
3383impl<I: Ip> GenericOverIp<I> for core::convert::Infallible {
3384 type Type = Self;
3385}
3386
3387#[derive(GenericOverIp, Default, Debug, PartialOrd, Ord, Eq, PartialEq, Hash)]
3389#[generic_over_ip(I, Ip)]
3390pub struct IpMarked<I: Ip, T> {
3391 inner: T,
3392 _marker: IpVersionMarker<I>,
3393}
3394
3395impl<I: Ip, T> Deref for IpMarked<I, T> {
3396 type Target = T;
3397
3398 fn deref(&self) -> &Self::Target {
3399 self.as_ref()
3400 }
3401}
3402
3403impl<I: Ip, T> DerefMut for IpMarked<I, T> {
3404 fn deref_mut(&mut self) -> &mut Self::Target {
3405 self.as_mut()
3406 }
3407}
3408impl<I: Ip, T> AsRef<T> for IpMarked<I, T> {
3409 fn as_ref(&self) -> &T {
3410 &self.inner
3411 }
3412}
3413
3414impl<I: Ip, T> AsMut<T> for IpMarked<I, T> {
3415 fn as_mut(&mut self) -> &mut T {
3416 &mut self.inner
3417 }
3418}
3419
3420impl<I: Ip, T> IpMarked<I, T> {
3421 pub fn new(inner: T) -> Self {
3423 Self { inner, _marker: IpVersionMarker::<I>::new() }
3424 }
3425
3426 pub fn into_inner(self) -> T {
3428 let Self { inner, _marker } = self;
3429 inner
3430 }
3431
3432 pub fn get(&self) -> &T {
3434 self.as_ref()
3435 }
3436
3437 pub fn get_mut(&mut self) -> &mut T {
3439 self.as_mut()
3440 }
3441}
3442
3443macro_rules! for_each_tuple_ {
3445 ( $m:ident !! ) => ( $m! { });
3446 ( $m:ident !! $h:ident, $($t:ident,)* ) => (
3447 $m! { $h $($t)* }
3448 for_each_tuple_! { $m !! $($t,)* }
3449 );
3450 }
3451
3452macro_rules! for_each_tuple {
3454 ($m:ident) => {
3455 for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, }
3456 };
3457}
3458
3459macro_rules! ip_generic_tuple {
3461 () => {
3462 impl<I: Ip> GenericOverIp<I> for () {
3463 type Type = Self;
3464 }
3465 };
3466 ( $name0:ident $($name:ident)* ) => (
3467 impl<P: Ip, $name0: GenericOverIp<P>, $($name: GenericOverIp<P>,)*>
3468 GenericOverIp<P> for ($name0, $($name,)*) {
3469 type Type = ($name0::Type, $($name::Type,)*);
3470 }
3471 );
3472 }
3473
3474for_each_tuple!(ip_generic_tuple);
3475
3476macro_rules! ip_generic {
3477 ( $type:ident < $($params:ident),* >) => {
3478 impl<IpType: Ip, $($params: GenericOverIp<IpType>),*>
3479 GenericOverIp<IpType> for $type<$($params),*> {
3480 type Type = $type<$($params::Type),*>;
3481 }
3482 };
3483 ( $type:ident) => {
3484 impl<IpType: Ip> GenericOverIp<IpType> for $type {
3485 type Type = Self;
3486 }
3487 }
3488}
3489
3490ip_generic!(bool);
3492ip_generic!(isize);
3493ip_generic!(i8);
3494ip_generic!(i16);
3495ip_generic!(i32);
3496ip_generic!(i64);
3497ip_generic!(usize);
3498ip_generic!(u8);
3499ip_generic!(u16);
3500ip_generic!(u32);
3501ip_generic!(u64);
3502ip_generic!(Option<T>);
3503ip_generic!(Result<R, E>);
3504#[cfg(feature = "std")]
3505ip_generic!(Vec<T>);
3506#[cfg(feature = "std")]
3507ip_generic!(Arc<T>);
3508
3509impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s T
3510where
3511 T::Type: 's,
3512{
3513 type Type = &'s T::Type;
3514}
3515
3516impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s mut T
3517where
3518 T::Type: 's,
3519{
3520 type Type = &'s mut T::Type;
3521}
3522
3523#[cfg(test)]
3524mod tests {
3525 use super::*;
3526 use test_case::test_case;
3527
3528 #[test]
3529 fn test_map_ip_associated_constant() {
3530 fn get_loopback_address<I: Ip>() -> SpecifiedAddr<I::Addr> {
3531 I::map_ip((), |()| Ipv4::LOOPBACK_ADDRESS, |()| Ipv6::LOOPBACK_ADDRESS)
3532 }
3533
3534 assert_eq!(get_loopback_address::<Ipv4>(), Ipv4::LOOPBACK_ADDRESS);
3535 assert_eq!(get_loopback_address::<Ipv6>(), Ipv6::LOOPBACK_ADDRESS);
3536 }
3537
3538 #[test]
3539 fn test_map_ip_different_behavior() {
3540 fn filter_v4<I: Ip>(addr: I::Addr) -> Option<I::Addr> {
3541 I::map_ip(addr, |addr| Some(addr), |_addr| None)
3542 }
3543
3544 assert_eq!(filter_v4::<Ipv4>(*Ipv4::LOOPBACK_ADDRESS), Some(*Ipv4::LOOPBACK_ADDRESS));
3545 assert_eq!(filter_v4::<Ipv6>(*Ipv6::LOOPBACK_ADDRESS), None);
3546 }
3547
3548 #[test]
3549 fn test_map_ip_extension_trait_fn() {
3550 trait FakeIpExt: Ip {
3551 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr;
3552 }
3553
3554 impl FakeIpExt for Ipv4 {
3555 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3556 let Ipv4Addr(mut bytes) = a;
3557 bytes.reverse();
3558 Ipv4Addr(bytes)
3559 }
3560 }
3561 impl FakeIpExt for Ipv6 {
3562 fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3563 let Ipv6Addr(mut bytes) = a;
3564 bytes.reverse();
3565 Ipv6Addr(bytes)
3566 }
3567 }
3568
3569 fn reverse_bytes<A: IpAddress>(addr: A) -> A
3570 where
3571 A::Version: FakeIpExt,
3572 {
3573 A::Version::map_ip(addr, Ipv4::reverse_addr_bytes, Ipv6::reverse_addr_bytes)
3574 }
3575
3576 assert_eq!(reverse_bytes(Ipv4Addr([1, 2, 3, 4])), Ipv4Addr([4, 3, 2, 1]));
3577 assert_eq!(
3578 reverse_bytes(Ipv6Addr([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])),
3579 Ipv6Addr([16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
3580 );
3581 }
3582
3583 #[test]
3584 fn test_map_ip_extension_trait_associated_type() {
3585 trait FakeIpExt: Ip {
3586 type PackedInt;
3587 }
3588 impl FakeIpExt for Ipv4 {
3589 type PackedInt = u32;
3590 }
3591 impl FakeIpExt for Ipv6 {
3592 type PackedInt = u128;
3593 }
3594
3595 #[derive(Debug, PartialEq)]
3596 struct Int<T>(T);
3597
3598 impl<T, I: FakeIpExt> GenericOverIp<I> for Int<T> {
3599 type Type = Int<I::PackedInt>;
3600 }
3601
3602 fn from_be_bytes<A: IpAddress>(addr: A) -> Int<<A::Version as FakeIpExt>::PackedInt>
3603 where
3604 A::Version: FakeIpExt,
3605 {
3606 A::Version::map_ip(
3607 addr,
3608 |Ipv4Addr(bytes)| Int(<Ipv4 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3609 |Ipv6Addr(bytes)| Int(<Ipv6 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3610 )
3611 }
3612
3613 assert_eq!(from_be_bytes(Ipv4::LOOPBACK_ADDRESS.get()), Int(0x7f000001u32));
3614 assert_eq!(from_be_bytes(Ipv6::LOOPBACK_ADDRESS.get()), Int(1u128));
3615 }
3616
3617 #[test]
3618 fn map_ip_twice() {
3619 struct FooV4 {
3620 field: Ipv4Addr,
3621 }
3622
3623 impl Default for FooV4 {
3624 fn default() -> Self {
3625 Self { field: Ipv4::UNSPECIFIED_ADDRESS }
3626 }
3627 }
3628
3629 struct FooV6 {
3630 field: Ipv6Addr,
3631 }
3632
3633 impl Default for FooV6 {
3634 fn default() -> Self {
3635 Self { field: Ipv6::UNSPECIFIED_ADDRESS }
3636 }
3637 }
3638
3639 trait IpExt {
3640 type Foo: Default;
3641 }
3642
3643 impl IpExt for Ipv4 {
3644 type Foo = FooV4;
3645 }
3646
3647 impl IpExt for Ipv6 {
3648 type Foo = FooV6;
3649 }
3650
3651 #[derive(GenericOverIp)]
3652 #[generic_over_ip(I, Ip)]
3653 struct Foo<I: IpExt>(I::Foo);
3654
3655 fn do_something<I: Ip + IpExt>(
3656 foo: Foo<I>,
3657 extra_foo: Foo<I>,
3658 captured_foo: Foo<I>,
3659 ) -> I::Addr {
3660 let addr: I::Addr = map_ip_twice!(I, foo, |Foo(foo)| { foo.field });
3661
3662 let _: I::Addr =
3665 map_ip_twice!(<<I as Ip>::Addr as IpAddress>::Version, extra_foo, |Foo(foo)| {
3666 let _: &Foo<I> = &captured_foo;
3670 foo.field
3671 });
3672
3673 addr
3674 }
3675
3676 assert_eq!(
3677 do_something(
3678 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3679 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3680 Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS })
3681 ),
3682 Ipv4::UNSPECIFIED_ADDRESS
3683 );
3684 assert_eq!(
3685 do_something(
3686 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3687 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3688 Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS })
3689 ),
3690 Ipv6::UNSPECIFIED_ADDRESS
3691 );
3692
3693 fn do_something_with_default_type_alias_shadowing<I: Ip>() -> (I::Addr, IpVersion) {
3694 let (field, IpInvariant(version)) = map_ip_twice!(I, (), |()| {
3695 let foo: Foo<I> = Foo(<I as IpExt>::Foo::default());
3698 (foo.0.field, IpInvariant(I::VERSION))
3699 },);
3700 (field, version)
3701 }
3702
3703 fn do_something_with_type_alias<I: Ip>() -> (I::Addr, IpVersion) {
3704 #[allow(dead_code)]
3707 type IpAlias = usize;
3708
3709 let (field, IpInvariant(version)) = map_ip_twice!(I as IpAlias, (), |()| {
3710 let foo: Foo<IpAlias> = Foo(<IpAlias as IpExt>::Foo::default());
3714 (foo.0.field, IpInvariant(IpAlias::VERSION))
3715 },);
3716 (field, version)
3717 }
3718
3719 assert_eq!(
3720 do_something_with_default_type_alias_shadowing::<Ipv4>(),
3721 (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3722 );
3723 assert_eq!(
3724 do_something_with_default_type_alias_shadowing::<Ipv6>(),
3725 (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3726 );
3727 assert_eq!(
3728 do_something_with_type_alias::<Ipv4>(),
3729 (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3730 );
3731 assert_eq!(
3732 do_something_with_type_alias::<Ipv6>(),
3733 (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3734 );
3735 }
3736
3737 #[test]
3738 fn test_loopback_unicast() {
3739 assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
3743 assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
3744 }
3745
3746 #[test]
3747 fn test_specified() {
3748 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_specified());
3755 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_specified());
3756
3757 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_unicast());
3760
3761 let unicast = Ipv6Addr([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
3762 assert!(unicast.is_unicast());
3763 assert!(unicast.is_specified());
3764
3765 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_multicast());
3768 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_multicast());
3769
3770 let multicast = Ipv4::MULTICAST_SUBNET.network;
3771 assert!(multicast.is_multicast());
3772 assert!(multicast.is_specified());
3773 let multicast = Ipv6::MULTICAST_SUBNET.network;
3774 assert!(multicast.is_multicast());
3775 assert!(multicast.is_specified());
3776
3777 assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_link_local());
3780 assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_link_local());
3781
3782 let link_local = Ipv4::LINK_LOCAL_UNICAST_SUBNET.network;
3783 assert!(link_local.is_link_local());
3784 assert!(link_local.is_specified());
3785 let link_local = Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network;
3786 assert!(link_local.is_link_local());
3787 assert!(link_local.is_specified());
3788 let link_local = Ipv6::LINK_LOCAL_UNICAST_SUBNET.network;
3789 assert!(link_local.is_link_local());
3790 assert!(link_local.is_specified());
3791 let mut link_local = Ipv6::MULTICAST_SUBNET.network;
3792 link_local.0[1] = 0x02;
3793 assert!(link_local.is_link_local());
3794 assert!(link_local.is_specified());
3795 assert!(Ipv6::LOOPBACK_ADDRESS.is_link_local());
3796 }
3797
3798 #[test]
3799 fn test_link_local() {
3800 assert!(Ipv4::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3802 assert!(Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network.is_link_local());
3803
3804 assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3806 assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_unicast_link_local());
3807 let mut addr = Ipv6::MULTICAST_SUBNET.network;
3808 for flags in 0..=0x0F {
3809 addr.0[1] = (flags << 4) | 0x02;
3811 assert!(addr.is_link_local());
3814 assert!(!addr.is_unicast_link_local());
3815 }
3816
3817 let mut addr = Ipv6::LOOPBACK_ADDRESS.get();
3821 addr.0[1] = 0x02;
3823 assert!(!addr.is_link_local());
3824 }
3825
3826 #[test]
3827 fn test_subnet_new() {
3828 assert_eq!(
3829 Subnet::new(Ipv4Addr::new([255, 255, 255, 255]), 32).unwrap(),
3830 Subnet { network: Ipv4Addr::new([255, 255, 255, 255]), prefix: 32 },
3831 );
3832 assert_eq!(
3834 Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 33),
3835 Err(SubnetError::PrefixTooLong)
3836 );
3837 assert_eq!(
3838 Subnet::from_host(Ipv4Addr::new([255, 255, 255, 255]), 33),
3839 Err(PrefixTooLongError)
3840 );
3841 assert_eq!(Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 8), Err(SubnetError::HostBitsSet));
3843 assert_eq!(
3845 Subnet::from_host(Ipv4Addr::new([255, 255, 0, 0]), 8),
3846 Ok(Subnet { network: Ipv4Addr::new([255, 0, 0, 0]), prefix: 8 })
3847 );
3848
3849 assert_eq!(
3850 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32).unwrap(),
3851 AddrSubnet {
3852 addr: SpecifiedAddr(Ipv4Addr::new([1, 2, 3, 4])),
3853 subnet: Subnet { network: Ipv4Addr::new([1, 2, 3, 4]), prefix: 32 }
3854 }
3855 );
3856 assert!(
3860 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::UNSPECIFIED_ADDRESS, 16)
3861 == Err(AddrSubnetError::InvalidWitness)
3862 );
3863 assert!(
3864 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv6::UNSPECIFIED_ADDRESS, 64)
3865 == Err(AddrSubnetError::InvalidWitness)
3866 );
3867 assert!(
3869 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 33)
3870 == Err(AddrSubnetError::PrefixTooLong)
3871 );
3872 assert!(
3873 AddrSubnet::<_, SpecifiedAddr<_>>::new(
3874 Ipv6Addr::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
3875 129,
3876 ) == Err(AddrSubnetError::PrefixTooLong)
3877 );
3878 assert!(
3880 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::LIMITED_BROADCAST_ADDRESS.get(), 16)
3881 == Err(AddrSubnetError::NotUnicastInSubnet)
3882 );
3883 assert!(
3885 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([192, 168, 255, 255]), 16)
3886 == Err(AddrSubnetError::NotUnicastInSubnet)
3887 );
3888 assert!(
3890 AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([224, 0, 0, 1]), 16)
3891 == Err(AddrSubnetError::NotUnicastInSubnet)
3892 );
3893 assert!(
3894 AddrSubnet::<_, SpecifiedAddr<_>>::new(
3895 Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
3896 64,
3897 ) == Err(AddrSubnetError::NotUnicastInSubnet)
3898 );
3899
3900 assert!(
3904 AddrSubnet::<_, LinkLocalAddr<Ipv4Addr>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32)
3905 == Err(AddrSubnetError::InvalidWitness)
3906 );
3907 }
3908
3909 #[test]
3910 fn test_is_unicast_in_subnet() {
3911 let subnet =
3913 Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).expect("1.2.0.0/16 is a valid subnet");
3914 assert!(Ipv4Addr::new([1, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3915 assert!(!Ipv4Addr::new([2, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3916
3917 let subnet =
3918 Subnet::new(Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 64)
3919 .expect("1::/64 is a valid subnet");
3920 assert!(
3921 Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3922 .is_unicast_in_subnet(&subnet)
3923 );
3924 assert!(
3925 !Ipv6Addr::from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3926 .is_unicast_in_subnet(&subnet)
3927 );
3928
3929 assert!(
3931 !Ipv4::UNSPECIFIED_ADDRESS
3932 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 16).unwrap())
3933 );
3934 assert!(
3935 !Ipv6::UNSPECIFIED_ADDRESS
3936 .is_unicast_in_subnet(&Subnet::new(Ipv6::UNSPECIFIED_ADDRESS, 64).unwrap())
3937 );
3938 assert!(
3941 !Ipv4::UNSPECIFIED_ADDRESS
3942 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 31).unwrap())
3943 );
3944 assert!(
3945 !Ipv4::UNSPECIFIED_ADDRESS
3946 .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 32).unwrap())
3947 );
3948 assert!(
3950 !Ipv4Addr::new([1, 2, 0, 0])
3951 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap())
3952 );
3953 assert!(
3955 Ipv4Addr::new([1, 2, 3, 0])
3956 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 31).unwrap())
3957 );
3958 assert!(
3959 Ipv4Addr::new([1, 2, 3, 0])
3960 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 32).unwrap())
3961 );
3962 assert!(
3964 !Ipv4::LIMITED_BROADCAST_ADDRESS
3965 .get()
3966 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([128, 0, 0, 0]), 1).unwrap())
3967 );
3968 assert!(
3970 !Ipv4Addr::new([1, 2, 255, 255])
3971 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap())
3972 );
3973 assert!(
3975 Ipv4Addr::new([1, 2, 255, 255])
3976 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 254]), 31).unwrap())
3977 );
3978 assert!(
3979 Ipv4Addr::new([1, 2, 255, 255])
3980 .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 255]), 32).unwrap())
3981 );
3982 assert!(!Ipv4Addr::new([224, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::MULTICAST_SUBNET));
3984 assert!(
3985 !Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3986 .is_unicast_in_subnet(&Ipv6::MULTICAST_SUBNET)
3987 );
3988 assert!(!Ipv4Addr::new([240, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::CLASS_E_SUBNET));
3990 }
3991
3992 macro_rules! add_mask_test {
3993 ($name:ident, $addr:ident, $from_ip:expr => {
3994 $($mask:expr => $to_ip:expr),*
3995 }) => {
3996 #[test]
3997 fn $name() {
3998 let from = $addr::from($from_ip);
3999 $(assert_eq!(from.mask($mask), $addr::from($to_ip), "(`{}`.mask({}))", from, $mask);)*
4000 }
4001 };
4002 ($name:ident, $addr:ident, $from_ip:expr => {
4003 $($mask:expr => $to_ip:expr),*,
4004 }) => {
4005 add_mask_test!($name, $addr, $from_ip => { $($mask => $to_ip),* });
4006 };
4007 }
4008
4009 add_mask_test!(v4_full_mask, Ipv4Addr, [255, 254, 253, 252] => {
4010 32 => [255, 254, 253, 252],
4011 28 => [255, 254, 253, 240],
4012 24 => [255, 254, 253, 0],
4013 20 => [255, 254, 240, 0],
4014 16 => [255, 254, 0, 0],
4015 12 => [255, 240, 0, 0],
4016 8 => [255, 0, 0, 0],
4017 4 => [240, 0, 0, 0],
4018 0 => [0, 0, 0, 0],
4019 });
4020
4021 add_mask_test!(v6_full_mask, Ipv6Addr,
4022 [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0] => {
4023 128 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0],
4024 112 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0x00, 0x00],
4025 96 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0x00, 0x00, 0x00, 0x00],
4026 80 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4027 64 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4028 48 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4029 32 => [0xFF, 0xFE, 0xFD, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4030 16 => [0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4031 8 => [0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4032 0 => [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
4033 }
4034 );
4035
4036 #[test_case([255, 255, 255, 0] => Ok(24))]
4037 #[test_case([255, 255, 254, 0] => Ok(23))]
4038 #[test_case([255, 255, 253, 0] => Err(NotSubnetMaskError))]
4039 #[test_case([255, 255, 0, 255] => Err(NotSubnetMaskError))]
4040 #[test_case([255, 255, 255, 255] => Ok(32))]
4041 #[test_case([0, 0, 0, 0] => Ok(0))]
4042 #[test_case([0, 0, 0, 255] => Err(NotSubnetMaskError))]
4043 fn test_ipv4_prefix_len_try_from_subnet_mask(
4044 subnet_mask: [u8; 4],
4045 ) -> Result<u8, NotSubnetMaskError> {
4046 let subnet_mask = Ipv4Addr::from(subnet_mask);
4047 PrefixLength::<Ipv4>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
4048 }
4049
4050 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(64))]
4051 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(63))]
4052 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
4053 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 1] => Err(NotSubnetMaskError))]
4054 #[test_case([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(0))]
4055 #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] => Ok(128))]
4056 #[test_case([0, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
4057 fn test_ipv6_prefix_len_try_from_subnet_mask(
4058 subnet_mask: [u8; 16],
4059 ) -> Result<u8, NotSubnetMaskError> {
4060 let subnet_mask = Ipv6Addr::from(subnet_mask);
4061 PrefixLength::<Ipv6>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
4062 }
4063
4064 #[test_case(0 => true)]
4065 #[test_case(1 => true)]
4066 #[test_case(32 => true)]
4067 #[test_case(33 => false)]
4068 #[test_case(128 => false)]
4069 #[test_case(129 => false)]
4070 #[test_case(255 => false)]
4071 fn test_ipv4_prefix_len_new(prefix_len: u8) -> bool {
4072 PrefixLength::<Ipv4>::new(prefix_len).is_ok()
4073 }
4074
4075 #[test_case(0 => true)]
4076 #[test_case(1 => true)]
4077 #[test_case(32 => true)]
4078 #[test_case(33 => true)]
4079 #[test_case(128 => true)]
4080 #[test_case(129 => false)]
4081 #[test_case(255 => false)]
4082 fn test_ipv6_prefix_len_new(prefix_len: u8) -> bool {
4083 PrefixLength::<Ipv6>::new(prefix_len).is_ok()
4084 }
4085
4086 #[test_case(0 => [0, 0, 0, 0])]
4087 #[test_case(6 => [252, 0, 0, 0])]
4088 #[test_case(16 => [255, 255, 0, 0])]
4089 #[test_case(25 => [255, 255, 255, 128])]
4090 #[test_case(32 => [255, 255, 255, 255])]
4091 fn test_ipv4_prefix_len_get_mask(prefix_len: u8) -> [u8; 4] {
4092 let Ipv4Addr(inner) = PrefixLength::<Ipv4>::new(prefix_len).unwrap().get_mask();
4093 inner
4094 }
4095
4096 #[test_case(0 => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
4097 #[test_case(6 => [0xFC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
4098 #[test_case(64 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])]
4099 #[test_case(65 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0])]
4100 #[test_case(128 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])]
4101 fn test_ipv6_prefix_len_get_mask(prefix_len: u8) -> [u8; 16] {
4102 let Ipv6Addr(inner) = PrefixLength::<Ipv6>::new(prefix_len).unwrap().get_mask();
4103 inner
4104 }
4105
4106 #[test]
4107 fn test_ipv6_solicited_node() {
4108 let addr = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
4109 let solicited = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
4110 assert_eq!(addr.to_solicited_node_address().get(), solicited);
4111 }
4112
4113 #[test]
4114 fn test_ipv6_address_types() {
4115 assert!(!Ipv6Addr::from([0; 16]).is_specified());
4116 assert!(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1]).is_loopback());
4117 let link_local = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
4118 assert!(link_local.is_link_local());
4119 assert!(link_local.is_valid_unicast());
4120 assert!(link_local.to_solicited_node_address().is_multicast());
4121 let global_unicast = Ipv6Addr::new([0x80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
4122 assert!(global_unicast.is_valid_unicast());
4123 assert!(global_unicast.to_solicited_node_address().is_multicast());
4124
4125 let multi = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
4126 assert!(multi.is_multicast());
4127 assert!(!multi.is_valid_unicast());
4128 }
4129
4130 #[test]
4131 fn test_const_witness() {
4132 assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
4135 assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
4136 assert!(Ipv4::LIMITED_BROADCAST_ADDRESS.0.is_specified());
4137 assert!(Ipv4::ALL_ROUTERS_MULTICAST_ADDRESS.0.is_multicast());
4138 assert!(Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4139 assert!(Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4140 }
4141
4142 #[test]
4143 fn test_ipv6_scope() {
4144 use Ipv6ReservedScope::*;
4145 use Ipv6Scope::*;
4146 use Ipv6UnassignedScope::*;
4147
4148 assert_eq!(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network.scope(), SiteLocal);
4150 assert_eq!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.scope(), LinkLocal);
4151 assert_eq!(Ipv6::UNSPECIFIED_ADDRESS.scope(), Global);
4152
4153 let assert_scope = |value, scope| {
4155 let mut addr = Ipv6::MULTICAST_SUBNET.network;
4156 addr.0[1] |= value;
4158 assert_eq!(addr.scope(), scope);
4159 };
4160 assert_scope(0, Reserved(Scope0));
4161 assert_scope(1, InterfaceLocal);
4162 assert_scope(2, LinkLocal);
4163 assert_scope(3, RealmLocal);
4164 assert_scope(4, AdminLocal);
4165 assert_scope(5, SiteLocal);
4166 assert_scope(6, Unassigned(Scope6));
4167 assert_scope(7, Unassigned(Scope7));
4168 assert_scope(8, OrganizationLocal);
4169 assert_scope(9, Unassigned(Scope9));
4170 assert_scope(0xA, Unassigned(ScopeA));
4171 assert_scope(0xB, Unassigned(ScopeB));
4172 assert_scope(0xC, Unassigned(ScopeC));
4173 assert_scope(0xD, Unassigned(ScopeD));
4174 assert_scope(0xE, Global);
4175 assert_scope(0xF, Reserved(ScopeF));
4176 }
4177
4178 #[test]
4179 fn test_ipv6_multicast_scope_id() {
4180 const ALL_SCOPES: &[Ipv6Scope] = &[
4181 Ipv6Scope::Reserved(Ipv6ReservedScope::Scope0),
4182 Ipv6Scope::InterfaceLocal,
4183 Ipv6Scope::LinkLocal,
4184 Ipv6Scope::RealmLocal,
4185 Ipv6Scope::AdminLocal,
4186 Ipv6Scope::SiteLocal,
4187 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope6),
4188 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope7),
4189 Ipv6Scope::OrganizationLocal,
4190 Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope9),
4191 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeA),
4192 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeB),
4193 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeC),
4194 Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeD),
4195 Ipv6Scope::Global,
4196 Ipv6Scope::Reserved(Ipv6ReservedScope::ScopeF),
4197 ];
4198 for (i, a) in ALL_SCOPES.iter().enumerate() {
4199 assert_eq!(a.multicast_scope_id(), i.try_into().unwrap());
4200 }
4201 }
4202
4203 #[test]
4204 fn test_ipv4_embedded() {
4205 assert_eq!(
4208 Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_compatible(),
4209 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4])
4210 );
4211 assert_eq!(
4212 Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_mapped().get(),
4213 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]),
4214 );
4215
4216 let compatible = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4]);
4219 let mapped = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]);
4220 let not_embedded = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 1, 2, 3, 4]);
4221 let v4 = Ipv4Addr::new([1, 2, 3, 4]);
4222
4223 assert_eq!(compatible.to_ipv4_compatible(), Some(v4));
4224 assert_eq!(compatible.to_ipv4_mapped(), None);
4225
4226 assert_eq!(mapped.to_ipv4_compatible(), None);
4227 assert_eq!(mapped.to_ipv4_mapped(), Some(v4));
4228
4229 assert_eq!(not_embedded.to_ipv4_compatible(), None);
4230 assert_eq!(not_embedded.to_ipv4_mapped(), None);
4231
4232 assert_eq!(
4233 NonMappedAddr::new(compatible),
4234 Some(unsafe { NonMappedAddr::new_unchecked(compatible) })
4235 );
4236 assert_eq!(NonMappedAddr::new(mapped), None);
4237 assert_eq!(
4238 NonMappedAddr::new(not_embedded),
4239 Some(unsafe { NonMappedAddr::new_unchecked(not_embedded) })
4240 );
4241 assert_eq!(NonMappedAddr::new(v4), Some(unsafe { NonMappedAddr::new_unchecked(v4) }));
4242 }
4243
4244 #[test]
4245 fn test_common_prefix_len_ipv6() {
4246 let ip1 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4247 let ip2 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4248 let ip3 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4249 let ip4 = Ipv6Addr::from([0xFF, 0xFF, 0xC0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4250 let compare_with_ip1 = |target, expect| {
4251 assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4252 };
4253 compare_with_ip1(ip1, 128);
4254 compare_with_ip1(ip2, 0);
4255 compare_with_ip1(ip3, 24);
4256 compare_with_ip1(ip4, 17);
4257 }
4258
4259 #[test]
4260 fn test_common_prefix_len_ipv4() {
4261 let ip1 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0]);
4262 let ip2 = Ipv4Addr::new([0, 0, 0, 0]);
4263 let ip3 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0xFF]);
4264 let ip4 = Ipv4Addr::new([0xFF, 0xFF, 0xC0, 0x20]);
4265 let compare_with_ip1 = |target, expect| {
4266 assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4267 };
4268 compare_with_ip1(ip1, 32);
4269 compare_with_ip1(ip2, 0);
4270 compare_with_ip1(ip3, 24);
4271 compare_with_ip1(ip4, 17);
4272 }
4273
4274 #[test]
4275 fn test_ipv6_display() {
4276 fn test_one(addr: Ipv6Addr, expect: Option<&str>) {
4280 let formatted = format!("{}", addr);
4281 if let Some(expect) = expect {
4282 assert_eq!(formatted, expect);
4283 }
4284
4285 let formatted_std = format!("{}", std::net::Ipv6Addr::from(addr.segments()));
4295 assert_eq!(formatted, formatted_std);
4296 }
4297
4298 test_one(Ipv6::UNSPECIFIED_ADDRESS, Some("::"));
4299 test_one(*Ipv6::LOOPBACK_ADDRESS, Some("::1"));
4300 test_one(Ipv6::MULTICAST_SUBNET.network, Some("ff00::"));
4301 test_one(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network, Some("fe80::"));
4302 test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4303 test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4304 test_one(*Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::2"));
4305 test_one(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network, Some("fec0::"));
4306 test_one(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), Some("1::"));
4307 test_one(Ipv6Addr::new([0, 0, 0, 1, 2, 3, 4, 5]), Some("::1:2:3:4:5"));
4308
4309 for byte in 0u8..=255 {
4314 test_one(
4315 Ipv6Addr::new([
4316 u16::from(byte & 0b1),
4317 u16::from((byte & 0b10) >> 1),
4318 u16::from((byte & 0b100) >> 2),
4319 u16::from((byte & 0b1000) >> 3),
4320 u16::from((byte & 0b10000) >> 4),
4321 u16::from((byte & 0b100000) >> 5),
4322 u16::from((byte & 0b1000000) >> 6),
4323 u16::from((byte & 0b10000000) >> 7),
4324 ]),
4325 None,
4326 );
4327 }
4328 }
4329
4330 #[test_case(Ipv4::UNSPECIFIED_ADDRESS, Ipv4AddressClass::A; "first_class_a")]
4331 #[test_case(Ipv4Addr::new([127, 255, 255, 255]), Ipv4AddressClass::A; "last_class_a")]
4332 #[test_case(Ipv4Addr::new([128, 0, 0, 0]), Ipv4AddressClass::B; "first_class_b")]
4333 #[test_case(Ipv4Addr::new([191, 255, 255, 255]), Ipv4AddressClass::B; "last_class_b")]
4334 #[test_case(Ipv4Addr::new([192, 0, 0, 0]), Ipv4AddressClass::C; "first_class_c")]
4335 #[test_case(Ipv4Addr::new([223, 255, 255, 255]), Ipv4AddressClass::C; "last_class_c")]
4336 #[test_case(Ipv4Addr::new([224, 0, 0, 0]), Ipv4AddressClass::D; "first_class_d")]
4337 #[test_case(Ipv4Addr::new([239, 255, 255, 255]), Ipv4AddressClass::D; "last_class_d")]
4338 #[test_case(Ipv4Addr::new([240, 0, 0, 0]), Ipv4AddressClass::E; "first_class_e")]
4339 #[test_case(Ipv4Addr::new([255, 255, 255, 255]), Ipv4AddressClass::E; "last_class_e")]
4340 fn ipv4addr_class(addr: Ipv4Addr, class: Ipv4AddressClass) {
4341 assert_eq!(addr.class(), class)
4342 }
4343
4344 #[test_case(
4345 Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 24).unwrap(),
4346 Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap()
4347 ; "ipv4_same_prefix")]
4348 #[test_case(
4349 Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap(),
4350 Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 32).unwrap()
4351 ; "ipv4_by_prefix")]
4352 #[test_case(
4353 Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4354 Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap()
4355 ; "ipv6_same_prefix")]
4356 #[test_case(
4357 Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4358 Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 128).unwrap()
4359 ; "ipv6_by_prefix")]
4360 fn subnet_ord<A: core::cmp::Ord>(a: Subnet<A>, b: Subnet<A>) {
4361 assert!(a < b);
4362 }
4363
4364 #[cfg(feature = "std")]
4365 mod std_tests {
4366 use super::*;
4367
4368 #[test]
4369 fn test_conversions() {
4370 let v4 = Ipv4Addr::new([127, 0, 0, 1]);
4371 let v6 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
4372 let std_v4 = net::Ipv4Addr::new(127, 0, 0, 1);
4373 let std_v6 = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
4374
4375 let converted: IpAddr = net::IpAddr::V4(std_v4).into();
4376 assert_eq!(converted, IpAddr::V4(v4));
4377 let converted: IpAddr = net::IpAddr::V6(std_v6).into();
4378 assert_eq!(converted, IpAddr::V6(v6));
4379
4380 let converted: net::IpAddr = IpAddr::V4(v4).into();
4381 assert_eq!(converted, net::IpAddr::V4(std_v4));
4382 let converted: net::IpAddr = IpAddr::V6(v6).into();
4383 assert_eq!(converted, net::IpAddr::V6(std_v6));
4384
4385 let converted: Ipv4Addr = std_v4.into();
4386 assert_eq!(converted, v4);
4387 let converted: Ipv6Addr = std_v6.into();
4388 assert_eq!(converted, v6);
4389
4390 let converted: net::Ipv4Addr = v4.into();
4391 assert_eq!(converted, std_v4);
4392 let converted: net::Ipv6Addr = v6.into();
4393 assert_eq!(converted, std_v6);
4394 }
4395 }
4396}
4397
4398#[cfg(test)]
4400mod macro_test {
4401 use super::*;
4402
4403 fn assert_ip_generic_is<T, I, Other>()
4405 where
4406 I: Ip,
4407 T: GenericOverIp<I, Type = Other>,
4408 {
4409 }
4412
4413 macro_rules! assert_ip_generic {
4414 ($name:ident, Ip $(,$($param:ident),*)?) => {
4415 assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4416 assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4417 assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4418 assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4419 };
4420 ($name:ident, IpAddress $(,$($param:ident),*)?) => {
4421 assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4422 assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4423 assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4424 assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4425 };
4426 ($name:ident $(,$($param:ident),*)?) => {
4427 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4428 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4429 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4430 assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4431 };
4432 }
4433
4434 #[test]
4435 fn struct_with_ip_version_parameter() {
4436 #[allow(dead_code)]
4437 #[derive(GenericOverIp)]
4438 #[generic_over_ip(I, Ip)]
4439 struct Generic<I: Ip> {
4440 addr: I::Addr,
4441 }
4442
4443 assert_ip_generic!(Generic, Ip);
4444 }
4445
4446 #[test]
4447 fn struct_with_unbounded_ip_version_parameter() {
4448 #[allow(dead_code)]
4449 #[derive(GenericOverIp)]
4450 #[generic_over_ip(I, Ip)]
4451 struct Generic<I> {
4452 addr: core::marker::PhantomData<I>,
4453 }
4454
4455 assert_ip_generic!(Generic, Ip);
4456 }
4457
4458 #[test]
4459 fn struct_with_ip_address_parameter() {
4460 #[allow(dead_code)]
4461 #[derive(GenericOverIp)]
4462 #[generic_over_ip(A, IpAddress)]
4463 struct Generic<A: IpAddress> {
4464 addr: A,
4465 }
4466
4467 assert_ip_generic!(Generic, IpAddress);
4468 }
4469
4470 #[test]
4471 fn struct_with_unbounded_ip_address_parameter() {
4472 #[allow(dead_code)]
4473 #[derive(GenericOverIp)]
4474 #[generic_over_ip(A, IpAddress)]
4475 struct Generic<A> {
4476 addr: A,
4477 }
4478
4479 assert_ip_generic!(Generic, IpAddress);
4480 }
4481
4482 #[test]
4483 fn struct_with_generic_over_ip_parameter() {
4484 #[derive(GenericOverIp)]
4485 #[generic_over_ip(I, Ip)]
4486 struct InnerGeneric<I: Ip> {
4487 addr: I::Addr,
4488 }
4489
4490 #[derive(GenericOverIp)]
4491 #[generic_over_ip(T, GenericOverIp)]
4492 struct Generic<T> {
4493 foo: T,
4494 }
4495
4496 fn do_something<I: Ip>(g: Generic<InnerGeneric<I>>) {
4497 I::map_ip(
4498 g,
4499 |g| {
4500 let _: Ipv4Addr = g.foo.addr;
4501 },
4502 |g| {
4503 let _: Ipv6Addr = g.foo.addr;
4504 },
4505 )
4506 }
4507
4508 do_something::<Ipv4>(Generic { foo: InnerGeneric { addr: Ipv4::UNSPECIFIED_ADDRESS } });
4509
4510 do_something::<Ipv6>(Generic { foo: InnerGeneric { addr: Ipv6::UNSPECIFIED_ADDRESS } });
4511 }
4512
4513 #[test]
4514 fn enum_with_ip_version_parameter() {
4515 #[allow(dead_code)]
4516 #[derive(GenericOverIp)]
4517 #[generic_over_ip(I, Ip)]
4518 enum Generic<I: Ip> {
4519 A(I::Addr),
4520 B(I::Addr),
4521 }
4522
4523 assert_ip_generic!(Generic, Ip);
4524 }
4525
4526 #[test]
4527 fn enum_with_unbounded_ip_version_parameter() {
4528 #[allow(dead_code)]
4529 #[derive(GenericOverIp)]
4530 #[generic_over_ip(I, Ip)]
4531 enum Generic<I> {
4532 A(core::marker::PhantomData<I>),
4533 B(core::marker::PhantomData<I>),
4534 }
4535
4536 assert_ip_generic!(Generic, Ip);
4537 }
4538
4539 #[test]
4540 fn enum_with_ip_address_parameter() {
4541 #[allow(dead_code)]
4542 #[derive(GenericOverIp)]
4543 #[generic_over_ip(A, IpAddress)]
4544 enum Generic<A: IpAddress> {
4545 A(A),
4546 B(A),
4547 }
4548
4549 assert_ip_generic!(Generic, IpAddress);
4550 }
4551
4552 #[test]
4553 fn enum_with_unbounded_ip_address_parameter() {
4554 #[allow(dead_code)]
4555 #[derive(GenericOverIp)]
4556 #[generic_over_ip(A, IpAddress)]
4557 enum Generic<A> {
4558 A(A),
4559 B(A),
4560 }
4561
4562 assert_ip_generic!(Generic, IpAddress);
4563 }
4564
4565 #[test]
4566 fn struct_with_ip_version_and_other_parameters() {
4567 #[allow(dead_code)]
4568 #[derive(GenericOverIp)]
4569 #[generic_over_ip(I, Ip)]
4570 struct AddrAndDevice<I: Ip, D> {
4571 addr: I::Addr,
4572 device: D,
4573 }
4574 struct Device;
4575
4576 assert_ip_generic!(AddrAndDevice, Ip, Device);
4577 }
4578
4579 #[test]
4580 fn enum_with_ip_version_and_other_parameters() {
4581 #[allow(dead_code)]
4582 #[derive(GenericOverIp)]
4583 #[generic_over_ip(I, Ip)]
4584 enum AddrOrDevice<I: Ip, D> {
4585 Addr(I::Addr),
4586 Device(D),
4587 }
4588 struct Device;
4589
4590 assert_ip_generic!(AddrOrDevice, Ip, Device);
4591 }
4592
4593 #[test]
4594 fn struct_with_ip_address_and_other_parameters() {
4595 #[allow(dead_code)]
4596 #[derive(GenericOverIp)]
4597 #[generic_over_ip(A, IpAddress)]
4598 struct AddrAndDevice<A: IpAddress, D> {
4599 addr: A,
4600 device: D,
4601 }
4602 struct Device;
4603
4604 assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4605 }
4606
4607 #[test]
4608 fn struct_with_unbounded_ip_address_and_other_parameters() {
4609 #[allow(dead_code)]
4610 #[derive(GenericOverIp)]
4611 #[generic_over_ip(A, IpAddress)]
4612 struct AddrAndDevice<A, D> {
4613 addr: A,
4614 device: D,
4615 }
4616 struct Device;
4617
4618 assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4619 }
4620
4621 #[test]
4622 fn enum_with_ip_address_and_other_parameters() {
4623 #[allow(dead_code)]
4624 #[derive(GenericOverIp, Debug, PartialEq)]
4625 #[generic_over_ip(A, IpAddress)]
4626 enum AddrOrDevice<A: IpAddress, D> {
4627 Addr(A),
4628 Device(D),
4629 }
4630 struct Device;
4631
4632 assert_ip_generic!(AddrOrDevice, IpAddress, Device);
4633 }
4634
4635 #[test]
4636 fn struct_invariant_over_ip() {
4637 #[allow(dead_code)]
4638 #[derive(GenericOverIp)]
4639 #[generic_over_ip()]
4640 struct Invariant(usize);
4641
4642 assert_ip_generic!(Invariant);
4643 }
4644
4645 #[test]
4646 fn enum_invariant_over_ip() {
4647 #[allow(dead_code)]
4648 #[derive(GenericOverIp)]
4649 #[generic_over_ip()]
4650 enum Invariant {
4651 Usize(usize),
4652 }
4653
4654 assert_ip_generic!(Invariant);
4655 }
4656
4657 #[test]
4658 fn struct_invariant_over_ip_with_other_params() {
4659 #[allow(dead_code)]
4660 #[derive(GenericOverIp)]
4661 #[generic_over_ip()]
4662 struct Invariant<B, C, D>(B, C, D);
4663
4664 assert_ip_generic!(Invariant, usize, bool, char);
4665 }
4666
4667 #[test]
4668 fn enum_invariant_over_ip_with_other_params() {
4669 #[allow(dead_code)]
4670 #[derive(GenericOverIp)]
4671 #[generic_over_ip()]
4672 enum Invariant<A, B, C> {
4673 A(A),
4674 B(B),
4675 C(C),
4676 }
4677
4678 assert_ip_generic!(Invariant, usize, bool, char);
4679 }
4680
4681 #[test]
4682 fn struct_with_ip_version_extension_parameter() {
4683 trait FakeIpExt: Ip {
4684 type Associated;
4685 }
4686 impl FakeIpExt for Ipv4 {
4687 type Associated = u8;
4688 }
4689 impl FakeIpExt for Ipv6 {
4690 type Associated = u16;
4691 }
4692
4693 #[allow(dead_code)]
4694 #[derive(GenericOverIp)]
4695 #[generic_over_ip(I, Ip)]
4696 struct Generic<I: FakeIpExt> {
4697 field: I::Associated,
4698 }
4699
4700 assert_ip_generic!(Generic, Ip);
4701 }
4702
4703 #[test]
4704 fn struct_with_ip_version_extension_parameter_but_no_ip_bound() {
4705 trait FakeIpExt: Ip {
4706 type Associated;
4707 }
4708 impl FakeIpExt for Ipv4 {
4709 type Associated = u8;
4710 }
4711 impl FakeIpExt for Ipv6 {
4712 type Associated = u16;
4713 }
4714
4715 #[allow(dead_code)]
4716 #[derive(GenericOverIp)]
4717 #[generic_over_ip(I, Ip)]
4718 struct Generic<I: FakeIpExt> {
4719 field: I::Associated,
4720 }
4721
4722 assert_ip_generic!(Generic, Ip);
4723 }
4724
4725 #[test]
4726 fn struct_with_ip_address_extension_parameter() {
4727 trait FakeIpAddressExt: IpAddress {
4728 type Associated;
4729 }
4730 impl FakeIpAddressExt for Ipv4Addr {
4731 type Associated = u8;
4732 }
4733 impl FakeIpAddressExt for Ipv6Addr {
4734 type Associated = u16;
4735 }
4736
4737 #[allow(dead_code)]
4738 #[derive(GenericOverIp)]
4739 #[generic_over_ip(A, IpAddress)]
4740 struct Generic<A: IpAddress + FakeIpAddressExt> {
4741 field: A::Associated,
4742 }
4743
4744 assert_ip_generic!(Generic, IpAddress);
4745 }
4746
4747 #[test]
4748 fn type_with_lifetime_and_ip_parameter() {
4749 #[allow(dead_code)]
4750 #[derive(GenericOverIp)]
4751 #[generic_over_ip(I, Ip)]
4752 struct Generic<'a, I: Ip> {
4753 field: &'a I::Addr,
4754 }
4755
4756 assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv4, Generic<'static, Ipv4>>();
4757 assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv6, Generic<'static, Ipv6>>();
4758 assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv4, Generic<'static, Ipv4>>();
4759 assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv6, Generic<'static, Ipv6>>();
4760 }
4761
4762 #[test]
4763 fn type_with_lifetime_and_no_ip_parameter() {
4764 #[allow(dead_code)]
4765 #[derive(GenericOverIp)]
4766 #[generic_over_ip()]
4767 struct Generic<'a> {
4768 field: &'a (),
4769 }
4770
4771 assert_ip_generic_is::<Generic<'static>, Ipv4, Generic<'static>>();
4772 assert_ip_generic_is::<Generic<'static>, Ipv6, Generic<'static>>();
4773 }
4774
4775 #[test]
4776 fn type_with_params_list_with_trailing_comma() {
4777 trait IpExtensionTraitWithVeryLongName {}
4778 trait OtherIpExtensionTraitWithVeryLongName {}
4779 trait LongNameToForceFormatterToBreakLineAndAddTrailingComma {}
4780 #[allow(dead_code)]
4782 #[derive(GenericOverIp)]
4783 #[generic_over_ip(I, Ip)]
4784 struct Generic<
4785 I: Ip
4786 + IpExtensionTraitWithVeryLongName
4787 + OtherIpExtensionTraitWithVeryLongName
4788 + LongNameToForceFormatterToBreakLineAndAddTrailingComma,
4789 > {
4790 field: I::Addr,
4791 }
4792 }
4793}