net_types/
ip.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// TODO: Edit this doc comment (it's copy+pasted from the Netstack3 core)
6
7//! Internet Protocol (IP) types.
8//!
9//! This module provides support for various types and traits relating to IPv4
10//! and IPv6, including a number of mechanisms for abstracting over details
11//! which are shared between IPv4 and IPv6.
12//!
13//! # `Ip` and `IpAddress`
14//!
15//! The most important traits are [`Ip`] and [`IpAddress`].
16//!
17//! `Ip` represents a version of the IP protocol - either IPv4 or IPv6 - and is
18//! implemented by [`Ipv4`] and [`Ipv6`]. These types exist only at the type
19//! level - they cannot be constructed at runtime. They provide a place to put
20//! constants and functionality which are not associated with a particular type,
21//! and they allow code to be written which is generic over the version of the
22//! IP protocol. For example:
23//!
24//! ```rust
25//! # use net_types::ip::{Ip, IpAddress, Subnet};
26//! struct Entry<A: IpAddress> {
27//!     subnet: Subnet<A>,
28//!     dest: Destination<A>,
29//! }
30//!
31//! enum Destination<A: IpAddress> {
32//!     Local { device_id: usize },
33//!     Remote { dst: A },
34//! }
35//!
36//! struct ForwardingTable<I: Ip> {
37//!     entries: Vec<Entry<I::Addr>>,
38//! }
39//! ```
40//!
41//! See also [`IpVersionMarker`].
42//!
43//! The `IpAddress` trait is implemented by the concrete [`Ipv4Addr`] and
44//! [`Ipv6Addr`] types.
45//!
46//! # Runtime types
47//!
48//! Sometimes, it is not known at compile time which version of a given type -
49//! IPv4 or IPv6 - is present. For these cases, enums are provided with variants
50//! for both IPv4 and IPv6. These are [`IpAddr`], [`SubnetEither`], and
51//! [`AddrSubnetEither`].
52//!
53//! # Composite types
54//!
55//! This modules also provides composite types such as [`Subnet`] and
56//! [`AddrSubnet`].
57
58use core::fmt::{self, Debug, Display, Formatter};
59use core::hash::Hash;
60use core::mem;
61use core::ops::{Deref, DerefMut};
62
63#[cfg(feature = "std")]
64use std::net;
65
66pub use net_types_macros::GenericOverIp;
67use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
68
69use crate::{
70    sealed, LinkLocalAddr, LinkLocalAddress, MappedAddress, MulticastAddr, MulticastAddress,
71    NonMappedAddr, Scope, ScopeableAddress, SpecifiedAddr, SpecifiedAddress, UnicastAddr,
72    UnicastAddress, Witness,
73};
74
75// NOTE on passing by reference vs by value: Clippy advises us to pass IPv4
76// addresses by value, and IPv6 addresses by reference. For concrete types, we
77// do the right thing. For the IpAddress trait, we use references in order to
78// optimize (albeit very slightly) for IPv6 performance.
79
80/// An IP protocol version.
81#[allow(missing_docs)]
82#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
83pub enum IpVersion {
84    V4,
85    V6,
86}
87
88/// Evaluates `expression` for any given `ip_version`.
89///
90/// `type_param` will be defined to be [`crate::ip::Ipv4`] for
91/// [`crate::ip::IpVersion::V4`], and [`crate::ip::Ipv6`] for
92/// [`crate::ip::IpVersion::V6`].
93///
94/// Example usage:
95///
96/// ```
97/// let ip_version: IpVersion = foo();
98/// for_any_ip_version!(ip_version, I, some_ip_generic_fn::<I>());
99/// ```
100#[macro_export]
101macro_rules! for_any_ip_version {
102    ($ip_version:expr, $type_param:ident, $expression:expr) => {
103        match $ip_version {
104            $crate::ip::IpVersion::V4 => {
105                type $type_param = $crate::ip::Ipv4;
106                $expression
107            }
108            $crate::ip::IpVersion::V6 => {
109                type $type_param = $crate::ip::Ipv6;
110                $expression
111            }
112        }
113    };
114}
115
116/// A zero-sized type that carries IP version information.
117///
118/// `IpVersionMarker` is typically used by types that are generic over IP
119/// version, but without any other associated data. In this sense,
120/// `IpVersionMarker` behaves similarly to [`PhantomData`].
121///
122/// [`PhantomData`]: core::marker::PhantomData
123#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, GenericOverIp)]
124#[generic_over_ip(I, Ip)]
125pub struct IpVersionMarker<I: Ip> {
126    _marker: core::marker::PhantomData<I>,
127}
128
129impl<I: Ip> IpVersionMarker<I> {
130    /// Creates a new `IpVersionMarker`.
131    // TODO(https://github.com/rust-lang/rust/issues/67792): Remove once
132    // `const_trait_impl` is stabilized.
133    pub const fn new() -> Self {
134        Self { _marker: core::marker::PhantomData }
135    }
136}
137
138impl<I: Ip> Default for IpVersionMarker<I> {
139    fn default() -> Self {
140        Self { _marker: core::marker::PhantomData }
141    }
142}
143
144impl<I: Ip> Debug for IpVersionMarker<I> {
145    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
146        write!(f, "IpVersionMarker<{}>", I::NAME)
147    }
148}
149
150/// An IP address.
151///
152/// By default, the contained address types are [`Ipv4Addr`] and [`Ipv6Addr`].
153/// However, any types can be provided. This is intended to support types like
154/// `IpAddr<SpecifiedAddr<Ipv4Addr>, SpecifiedAddr<Ipv6Addr>>`. `From` is
155/// implemented to support conversions in both directions between
156/// `IpAddr<SpecifiedAddr<Ipv4Addr>, SpecifiedAddr<Ipv6Addr>>` and
157/// `SpecifiedAddr<IpAddr>`, and similarly for other witness types.
158#[allow(missing_docs)]
159#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
160pub enum IpAddr<V4 = Ipv4Addr, V6 = Ipv6Addr> {
161    V4(V4),
162    V6(V6),
163}
164
165impl<V4: Display, V6: Display> Display for IpAddr<V4, V6> {
166    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
167        match self {
168            Self::V4(v4) => v4.fmt(f),
169            Self::V6(v6) => v6.fmt(f),
170        }
171    }
172}
173
174impl<V4, V6> IpAddr<V4, V6> {
175    /// Transposes an `IpAddr` of a witness type to a witness type of an
176    /// `IpAddr`.
177    ///
178    /// For example, `transpose` can be used to convert an
179    /// `IpAddr<SpecifiedAddr<Ipv4Addr>, SpecifiedAddr<Ipv6Addr>>` into a
180    /// `SpecifiedAddr<IpAddr<Ipv4Addr, Ipv6Addr>>`.
181    pub fn transpose<W: IpAddrWitness<V4 = V4, V6 = V6>>(self) -> W {
182        match self {
183            IpAddr::V4(addr) => W::from_v4(addr),
184            IpAddr::V6(addr) => W::from_v6(addr),
185        }
186    }
187}
188
189impl<A: IpAddress> From<A> for IpAddr {
190    #[inline]
191    fn from(addr: A) -> IpAddr {
192        addr.to_ip_addr()
193    }
194}
195
196impl<A: IpAddress, const N: usize> From<[A; N]> for IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
197    #[inline]
198    fn from(addrs: [A; N]) -> Self {
199        A::array_into_ip_addr(addrs)
200    }
201}
202
203#[cfg(feature = "std")]
204impl From<net::IpAddr> for IpAddr {
205    #[inline]
206    fn from(addr: net::IpAddr) -> IpAddr {
207        match addr {
208            net::IpAddr::V4(addr) => IpAddr::V4(addr.into()),
209            net::IpAddr::V6(addr) => IpAddr::V6(addr.into()),
210        }
211    }
212}
213
214#[cfg(feature = "std")]
215impl From<IpAddr> for net::IpAddr {
216    fn from(addr: IpAddr) -> net::IpAddr {
217        match addr {
218            IpAddr::V4(addr) => net::IpAddr::V4(addr.into()),
219            IpAddr::V6(addr) => net::IpAddr::V6(addr.into()),
220        }
221    }
222}
223
224impl IpVersion {
225    /// The number for this IP protocol version.
226    ///
227    /// 4 for `V4` and 6 for `V6`.
228    #[inline]
229    pub fn version_number(self) -> u8 {
230        match self {
231            IpVersion::V4 => 4,
232            IpVersion::V6 => 6,
233        }
234    }
235
236    /// Is this IPv4?
237    #[inline]
238    pub fn is_v4(self) -> bool {
239        self == IpVersion::V4
240    }
241
242    /// Is this IPv6?
243    #[inline]
244    pub fn is_v6(self) -> bool {
245        self == IpVersion::V6
246    }
247}
248
249/// The maximum transmit unit, i.e., the maximum size of an entire IP packet
250/// one link can transmit.
251#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
252pub struct Mtu(u32);
253
254impl Mtu {
255    /// Creates MTU from the maximum size of an entire IP packet in bytes.
256    pub const fn new(mtu: u32) -> Self {
257        Self(mtu)
258    }
259
260    /// Gets the numeric value of the MTU.
261    pub const fn get(&self) -> u32 {
262        let Self(mtu) = self;
263        *mtu
264    }
265
266    /// Creates a new `Mtu` with the maximum possible representation.
267    pub const fn max() -> Self {
268        Self(u32::MAX)
269    }
270
271    /// Equivalent to [`Mtu::max`], but with a name more telling for usage in
272    /// contexts where many `Mtu` instances are composed to enforce a minimum
273    /// `Mtu` value.
274    pub const fn no_limit() -> Self {
275        Self::max()
276    }
277}
278
279impl From<Mtu> for u32 {
280    fn from(Mtu(mtu): Mtu) -> Self {
281        mtu
282    }
283}
284
285impl From<Mtu> for usize {
286    fn from(Mtu(mtu): Mtu) -> Self {
287        mtu.try_into().expect("mtu must fit usize")
288    }
289}
290
291/// A trait for IP protocol versions.
292///
293/// `Ip` encapsulates the details of a version of the IP protocol. It includes a
294/// runtime representation of the protocol version ([`VERSION`]), the type of
295/// addresses for this version ([`Addr`]), and a number of constants which exist
296/// in both protocol versions. This trait is sealed, and there are guaranteed to
297/// be no other implementors besides these. Code - including unsafe code - may
298/// rely on this assumption for its correctness and soundness.
299///
300/// Note that the implementors of this trait cannot be instantiated; they only
301/// exist at the type level.
302///
303/// [`VERSION`]: Ip::VERSION
304/// [`Addr`]: Ip::Addr
305pub trait Ip:
306    Sized
307    + Clone
308    + Copy
309    + Debug
310    + Default
311    + Eq
312    + Hash
313    + Ord
314    + PartialEq
315    + PartialOrd
316    + Send
317    + Sync
318    + sealed::Sealed
319    + 'static
320{
321    /// The IP version.
322    ///
323    /// `V4` for IPv4 and `V6` for IPv6.
324    const VERSION: IpVersion;
325
326    /// The zero-sized-type IP version marker.
327    const VERSION_MARKER: IpVersionMarker<Self>;
328
329    /// The unspecified address.
330    ///
331    /// This is 0.0.0.0 for IPv4 and :: for IPv6.
332    const UNSPECIFIED_ADDRESS: Self::Addr;
333
334    /// The default loopback address.
335    ///
336    /// When sending packets to a loopback interface, this address is used as
337    /// the source address. It is an address in the [`LOOPBACK_SUBNET`].
338    ///
339    /// [`LOOPBACK_SUBNET`]: Ip::LOOPBACK_SUBNET
340    const LOOPBACK_ADDRESS: SpecifiedAddr<Self::Addr>;
341
342    /// The subnet of loopback addresses.
343    ///
344    /// Addresses in this subnet must not appear outside a host, and may only be
345    /// used for loopback interfaces.
346    const LOOPBACK_SUBNET: Subnet<Self::Addr>;
347
348    /// The subnet of multicast addresses.
349    const MULTICAST_SUBNET: Subnet<Self::Addr>;
350
351    /// The subnet of link-local unicast addresses.
352    ///
353    /// Note that some multicast addresses are also link-local. In IPv4, these
354    /// are contained in the [link-local multicast subnet]. In IPv6, the
355    /// link-local multicast addresses are not organized into a single subnet;
356    /// instead, whether a multicast IPv6 address is link-local is a function of
357    /// its scope.
358    ///
359    /// [link-local multicast subnet]: Ipv4::LINK_LOCAL_MULTICAST_SUBNET
360    const LINK_LOCAL_UNICAST_SUBNET: Subnet<Self::Addr>;
361
362    /// "IPv4" or "IPv6".
363    const NAME: &'static str;
364
365    /// The minimum link MTU for this version.
366    ///
367    /// Every internet link supporting this IP version must have a maximum
368    /// transmission unit (MTU) of at least this many bytes. This MTU applies to
369    /// the size of an IP packet, and does not include any extra bytes used by
370    /// encapsulating packets (Ethernet frames, GRE packets, etc).
371    const MINIMUM_LINK_MTU: Mtu;
372
373    /// The address type for this IP version.
374    ///
375    /// [`Ipv4Addr`] for IPv4 and [`Ipv6Addr`] for IPv6.
376    type Addr: IpAddress<Version = Self>
377        + GenericOverIp<Self, Type = Self::Addr>
378        + GenericOverIp<Ipv4, Type = Ipv4Addr>
379        + GenericOverIp<Ipv6, Type = Ipv6Addr>;
380
381    /// Apply one of the given functions to the input and return the result.
382    ///
383    /// This makes it possible to implement specialized behavior for IPv4 and
384    /// IPv6 versions that is more versatile than matching on [`Ip::VERSION`].
385    /// With a `match` expression, all branches must produce a value of the
386    /// same type. `map_ip` relaxes that restriction by instead requiring that
387    /// inputs and outputs are [`GenericOverIp`].
388    ///
389    /// Using `map_ip`, you can write generic code with specialized
390    /// implementations for different IP versions where some or all of the input
391    /// and output arguments have a type parameter `I: Ip`. As an example,
392    /// consider the following:
393    ///
394    /// ```
395    /// // Swaps the order of the addresses only if `I=Ipv4`.
396    /// fn swap_only_if_ipv4<I: Ip>(addrs: (I::Addr, I::Addr)) -> (I::Addr, I::Addr) {
397    ///    I::map_ip::<(I::Addr, I::Addr), (I::Addr, I::Addr)>(
398    ///        addrs,
399    ///        |(a, b): (Ipv4Addr, Ipv4Addr)| (b, a),
400    ///        |ab: (Ipv6Addr, Ipv6Addr)| ab
401    ///    )
402    /// }
403    /// ```
404    ///
405    /// Note that the input and output arguments both depend on the type
406    /// parameter `I`, but the closures take an [`Ipv4Addr`] or [`Ipv6Addr`].
407    ///
408    /// Types that don't implement `GenericOverIp` can be wrapped in
409    /// [`IpInvariant`], which implements `GenericOverIp` assuming the type
410    /// inside doesn't have any IP-related components.
411    fn map_ip<
412        In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
413        Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
414    >(
415        input: In,
416        v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
417        v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
418    ) -> Out;
419
420    /// Apply one of the given functions to the input and return the result.
421    ///
422    /// This is similar to `map_ip`, except only the input type is required to
423    /// be [`GenericOverIp`], while the output type is invariant. This allows
424    /// callers to more conveniently write this use case without having to wrap
425    /// the result in a type like [`IpInvariant`].
426    fn map_ip_in<
427        In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
428        Out,
429    >(
430        input: In,
431        v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> Out,
432        v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> Out,
433    ) -> Out {
434        Self::map_ip::<_, IpInvariant<_>>(
435            input,
436            |input| IpInvariant(v4(input)),
437            |input| IpInvariant(v6(input)),
438        )
439        .into_inner()
440    }
441
442    /// Apply one of the given functions to the input and return the result.
443    ///
444    /// This is similar to `map_ip`, except only the output type is required to
445    /// be [`GenericOverIp`], while the input type is invariant. This allows
446    /// callers to more conveniently write this use case without having to wrap
447    /// the input in a type like [`IpInvariant`].
448    fn map_ip_out<
449        In,
450        Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
451    >(
452        input: In,
453        v4: impl FnOnce(In) -> <Out as GenericOverIp<Ipv4>>::Type,
454        v6: impl FnOnce(In) -> <Out as GenericOverIp<Ipv6>>::Type,
455    ) -> Out {
456        Self::map_ip(
457            IpInvariant(input),
458            |IpInvariant(input)| v4(input),
459            |IpInvariant(input)| v6(input),
460        )
461    }
462}
463
464/// Invokes `I::map_ip`, passing the same function body as both arguments.
465///
466/// The first argument is always the `I` on which to invoke `I::map_ip`.
467/// Optionally, this can include an alias (`I as IpAlias`) that should be bound
468/// to `Ipv4` and `Ipv6` for each instantiation of the function body. (If the
469/// `Ip` argument passed is a simple identifier, then it is automatically
470/// aliased in this way.)
471/// The next argument is the input to thread through `map_ip` to the function,
472/// and the final argument is the function to be duplicated to serve as the
473/// closures passed to `map_ip`.
474///
475/// This macro helps avoid code duplication when working with types that are
476/// _not_ GenericOverIp, but have identical shapes such that the actual text of
477/// the code you are writing is identical. This should be very rare, and is
478/// generally limited to cases where we are interfacing with code that we don't
479/// have the ability to make generic-over-IP -- when possible, it's better to
480/// push `I: Ip` generics further through the types you are working with instead
481/// so that you can avoid using `map_ip` entirely.
482///
483/// Example:
484///
485/// ```
486/// // Imagine that `IpExt` is implemented for concrete `Ipv4` and `Ipv6` but
487/// // not for blanket `I: Ip`.
488/// struct Foo<I: IpExt>;
489///
490/// struct FooFactory;
491/// impl FooFactory {
492///     fn get<I: IpExt>(&self) -> Foo<I> {
493///         unimplemented!()
494///     }
495/// }
496///
497/// struct FooSink<I: IpExt>;
498/// impl<I: IpExt> FooSink<I> {
499///     fn use_foo(&self, foo: Foo<I>) {
500///         unimplemented!()
501///     }
502/// }
503///
504/// fn do_something<I: Ip>(factory: FooFactory) -> Foo<I> {
505///     map_ip_twice!(
506///         I,
507///         (),
508///         |()| {
509///            // This works because even though the `I` from the function decl
510///            // doesn't have an `IpExt` bound, it's aliased to either `Ipv4`
511///            // or `Ipv6` here.
512///            factory.get::<I>()
513///         },
514///     )
515/// }
516///
517/// fn do_something_else<I: IpExt>(factory: FooFactory, foo_sink: FooSink<I>) {
518///     map_ip_twice!(
519///         // Introduce different alias to avoid shadowing `I`.
520///         I as IpAlias,
521///         (),
522///         |()| {
523///             let foo_with_orig_ip = factory.get::<I>();
524///             // The fact that `I` was not shadowed allows us to make use of
525///             // `foo_sink` by capture rather than needing to thread it
526///             // through the generic-over-IP input.
527///             foo_sink.use_foo(foo_with_orig_ip)
528///         },
529///     )
530/// }
531/// ```
532#[macro_export]
533macro_rules! map_ip_twice {
534    // This case triggers if we're passed an `Ip` implementor that is a simple
535    // identifier in-scope (e.g. `I`), which allows us to automatically alias it
536    // to `Ipv4` and `Ipv6` in each `$fn` instantiation.
537    ($ip:ident, $input:expr, $fn:expr $(,)?) => {
538        $crate::map_ip_twice!($ip as $ip, $input, $fn)
539    };
540    // This case triggers if we're passed an `Ip` implementor that is _not_ an
541    // identifier, and thus we can't use it as the left-hand-side of a type
542    // alias binding (e.g. `<A as IpAddress>::Version`).
543    ($ip:ty, $input:expr, $fn:expr $(,)?) => {
544        <$ip as $crate::ip::Ip>::map_ip($input, { $fn }, { $fn })
545    };
546    ($ip:ty as $iptypealias:ident, $input:expr, $fn:expr $(,)?) => {
547        <$ip as $crate::ip::Ip>::map_ip(
548            $input,
549            {
550                #[allow(dead_code)]
551                type $iptypealias = $crate::ip::Ipv4;
552                $fn
553            },
554            {
555                #[allow(dead_code)]
556                type $iptypealias = $crate::ip::Ipv6;
557                $fn
558            },
559        )
560    };
561}
562
563/// IPv4.
564///
565/// `Ipv4` implements [`Ip`] for IPv4.
566///
567/// Note that this type has no value constructor. It is used purely at the type
568/// level. Attempting to construct it by calling `Default::default` will panic.
569#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
570pub enum Ipv4 {}
571
572impl Default for Ipv4 {
573    fn default() -> Ipv4 {
574        panic!("Ipv4 default")
575    }
576}
577
578impl sealed::Sealed for Ipv4 {}
579
580impl Ip for Ipv4 {
581    const VERSION: IpVersion = IpVersion::V4;
582    const VERSION_MARKER: IpVersionMarker<Self> = IpVersionMarker::new();
583
584    // TODO(https://fxbug.dev/42163997): Document the standard in which this
585    // constant is defined.
586    const UNSPECIFIED_ADDRESS: Ipv4Addr = Ipv4Addr::new([0, 0, 0, 0]);
587    /// The default IPv4 address used for loopback, defined in [RFC 5735 Section
588    /// 3].
589    ///
590    /// Note that while this address is the most commonly used address for
591    /// loopback traffic, any address in the [`LOOPBACK_SUBNET`] may be used.
592    ///
593    /// [RFC 5735 Section 3]: https://datatracker.ietf.org/doc/html/rfc5735#section-3
594    /// [`LOOPBACK_SUBNET`]: Ipv4::LOOPBACK_SUBNET
595    const LOOPBACK_ADDRESS: SpecifiedAddr<Ipv4Addr> =
596        unsafe { SpecifiedAddr::new_unchecked(Ipv4Addr::new([127, 0, 0, 1])) };
597    /// The IPv4 loopback subnet, defined in [RFC 1122 Section 3.2.1.3].
598    ///
599    /// [RFC 1122 Section 3.2.1.3]: https://www.rfc-editor.org/rfc/rfc1122.html#section-3.2.1.3
600    const LOOPBACK_SUBNET: Subnet<Ipv4Addr> =
601        Subnet { network: Ipv4Addr::new([127, 0, 0, 0]), prefix: 8 };
602    /// The IPv4 Multicast subnet, defined in [RFC 1112 Section 4].
603    ///
604    /// [RFC 1112 Section 4]: https://www.rfc-editor.org/rfc/rfc1112.html#section-4
605    const MULTICAST_SUBNET: Subnet<Ipv4Addr> = Self::CLASS_D_SUBNET;
606    /// The subnet of link-local unicast IPv4 addresses, outlined in [RFC 3927
607    /// Section 2.1].
608    ///
609    /// [RFC 3927 Section 2.1]: https://tools.ietf.org/html/rfc3927#section-2.1
610    const LINK_LOCAL_UNICAST_SUBNET: Subnet<Ipv4Addr> =
611        Subnet { network: Ipv4Addr::new([169, 254, 0, 0]), prefix: 16 };
612    const NAME: &'static str = "IPv4";
613    /// The IPv4 minimum link MTU.
614    ///
615    /// Per [RFC 791 Section 3.2], "[\e\]very internet module must be able to
616    /// forward a datagram of 68 octets without further fragmentation."
617    ///
618    /// [RFC 791 Section 3.2]: https://tools.ietf.org/html/rfc791#section-3.2
619    const MINIMUM_LINK_MTU: Mtu = Mtu(68);
620    type Addr = Ipv4Addr;
621
622    fn map_ip<
623        In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
624        Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
625    >(
626        input: In,
627        v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
628        _v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
629    ) -> Out {
630        v4(input)
631    }
632}
633
634impl Ipv4 {
635    /// The limited broadcast address.
636    ///
637    /// The limited broadcast address is considered to be a broadcast address on
638    /// all networks regardless of subnet address. This is distinct from the
639    /// subnet-specific broadcast address (e.g., 192.168.255.255 on the subnet
640    /// 192.168.0.0/16). It is defined in the [IANA IPv4 Special-Purpose Address
641    /// Registry].
642    ///
643    /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
644    pub const LIMITED_BROADCAST_ADDRESS: SpecifiedAddr<Ipv4Addr> =
645        unsafe { SpecifiedAddr::new_unchecked(Ipv4Addr::new([255, 255, 255, 255])) };
646
647    /// The Class A subnet.
648    ///
649    /// The Class A subnet is defined in [RFC 1812 section 2.2.5.1].
650    ///
651    /// [RFC 1812 section 2.2.5.1]: https://datatracker.ietf.org/doc/html/rfc1812#section-2.2.5.1
652    pub const CLASS_A_SUBNET: Subnet<Ipv4Addr> =
653        Subnet { network: Ipv4Addr::new([0, 0, 0, 0]), prefix: 1 };
654
655    /// The Class B subnet.
656    ///
657    /// The Class B subnet is defined in [RFC 1812 section 2.2.5.1].
658    ///
659    /// [RFC 1812 section 2.2.5.1]: https://datatracker.ietf.org/doc/html/rfc1812#section-2.2.5.1
660    pub const CLASS_B_SUBNET: Subnet<Ipv4Addr> =
661        Subnet { network: Ipv4Addr::new([128, 0, 0, 0]), prefix: 2 };
662
663    /// The Class C subnet.
664    ///
665    /// The Class C subnet is defined in [RFC 1812 section 2.2.5.1].
666    ///
667    /// [RFC 1812 section 2.2.5.1]: https://datatracker.ietf.org/doc/html/rfc1812#section-2.2.5.1
668    pub const CLASS_C_SUBNET: Subnet<Ipv4Addr> =
669        Subnet { network: Ipv4Addr::new([192, 0, 0, 0]), prefix: 3 };
670
671    /// The Class D subnet.
672    ///
673    /// This subnet is also known as the multicast subnet.
674    ///
675    /// The Class D subnet is defined in [RFC 1812 section 2.2.5.1].
676    ///
677    /// [RFC 1812 section 2.2.5.1]: https://datatracker.ietf.org/doc/html/rfc1812#section-2.2.5.1
678    pub const CLASS_D_SUBNET: Subnet<Ipv4Addr> =
679        Subnet { network: Ipv4Addr::new([224, 0, 0, 0]), prefix: 4 };
680
681    /// The Class E subnet.
682    ///
683    /// The Class E subnet is meant for experimental purposes, and should not be
684    /// used on the general internet. [RFC 1812 Section 5.3.7] suggests that
685    /// routers SHOULD discard packets with a source address in the Class E
686    /// subnet. The Class E subnet is defined in [RFC 1112 Section 4].
687    ///
688    /// [RFC 1812 Section 5.3.7]: https://tools.ietf.org/html/rfc1812#section-5.3.7
689    /// [RFC 1112 Section 4]: https://datatracker.ietf.org/doc/html/rfc1112#section-4
690    pub const CLASS_E_SUBNET: Subnet<Ipv4Addr> =
691        Subnet { network: Ipv4Addr::new([240, 0, 0, 0]), prefix: 4 };
692
693    /// The subnet of link-local multicast addresses, outlined in [RFC 5771
694    /// Section 4].
695    ///
696    /// [RFC 5771 Section 4]: https://tools.ietf.org/html/rfc5771#section-4
697    pub const LINK_LOCAL_MULTICAST_SUBNET: Subnet<Ipv4Addr> =
698        Subnet { network: Ipv4Addr::new([224, 0, 0, 0]), prefix: 24 };
699
700    /// The multicast address subscribed to by all systems on the local network,
701    /// defined in the [IPv4 Multicast Address Space Registry].
702    ///
703    /// [IPv4 Multicast Address Space Registry]: https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
704    pub const ALL_SYSTEMS_MULTICAST_ADDRESS: MulticastAddr<Ipv4Addr> =
705        unsafe { MulticastAddr::new_unchecked(Ipv4Addr::new([224, 0, 0, 1])) };
706
707    /// The multicast address subscribed to by all routers on the local network,
708    /// defined in the [IPv4 Multicast Address Space Registry].
709    ///
710    /// [IPv4 Multicast Address Space Registry]: https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
711    pub const ALL_ROUTERS_MULTICAST_ADDRESS: MulticastAddr<Ipv4Addr> =
712        unsafe { MulticastAddr::new_unchecked(Ipv4Addr::new([224, 0, 0, 2])) };
713}
714
715/// IPv6.
716///
717/// `Ipv6` implements [`Ip`] for IPv6.
718///
719/// Note that this type has no value constructor. It is used purely at the type
720/// level. Attempting to construct it by calling `Default::default` will panic.
721#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
722pub enum Ipv6 {}
723
724impl Default for Ipv6 {
725    fn default() -> Ipv6 {
726        panic!("Ipv6 default")
727    }
728}
729
730impl sealed::Sealed for Ipv6 {}
731
732impl Ip for Ipv6 {
733    const VERSION: IpVersion = IpVersion::V6;
734    const VERSION_MARKER: IpVersionMarker<Self> = IpVersionMarker::new();
735    /// The unspecified IPv6 address, defined in [RFC 4291 Section 2.5.2].
736    ///
737    /// Per RFC 4291:
738    ///
739    /// > The address 0:0:0:0:0:0:0:0 is called the unspecified address.  It
740    /// > must never be assigned to any node.  It indicates the absence of an
741    /// > address.  One example of its use is in the Source Address field of any
742    /// > IPv6 packets sent by an initializing host before it has learned its
743    /// > own address.
744    /// >
745    /// > The unspecified address must not be used as the destination address of
746    /// > IPv6 packets or in IPv6 Routing headers.  An IPv6 packet with a source
747    /// > address of unspecified must never be forwarded by an IPv6 router.
748    ///
749    /// [RFC 4291 Section 2.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2
750    const UNSPECIFIED_ADDRESS: Ipv6Addr = Ipv6Addr::new([0; 8]);
751    /// The loopback IPv6 address, defined in [RFC 4291 Section 2.5.3].
752    ///
753    /// Per RFC 4291:
754    ///
755    /// > The unicast address 0:0:0:0:0:0:0:1 is called the loopback address.
756    /// > It may be used by a node to send an IPv6 packet to itself.  It must
757    /// > not be assigned to any physical interface.  It is treated as having
758    /// > Link-Local scope, and may be thought of as the Link-Local unicast
759    /// > address of a virtual interface (typically called the "loopback
760    /// > interface") to an imaginary link that goes nowhere.
761    /// >
762    /// > The loopback address must not be used as the source address in IPv6
763    /// > packets that are sent outside of a single node.  An IPv6 packet with
764    /// > a destination address of loopback must never be sent outside of a
765    /// > single node and must never be forwarded by an IPv6 router.  A packet
766    /// > received on an interface with a destination address of loopback must
767    /// > be dropped.
768    ///
769    /// [RFC 4291 Section 2.5.3]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3
770    const LOOPBACK_ADDRESS: SpecifiedAddr<Ipv6Addr> =
771        unsafe { SpecifiedAddr::new_unchecked(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1])) };
772    /// The subnet of loopback IPv6 addresses, defined in [RFC 4291 Section 2.4].
773    ///
774    /// Note that the IPv6 loopback subnet is a /128, meaning that it contains
775    /// only one address - the [`LOOPBACK_ADDRESS`].
776    ///
777    /// [RFC 4291 Section 2.4]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
778    /// [`LOOPBACK_ADDRESS`]: Ipv6::LOOPBACK_ADDRESS
779    const LOOPBACK_SUBNET: Subnet<Ipv6Addr> =
780        Subnet { network: Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1]), prefix: 128 };
781    /// The subnet of multicast IPv6 addresses, defined in [RFC 4291 Section
782    /// 2.7].
783    ///
784    /// [RFC 4291 Section 2.7]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.7
785    const MULTICAST_SUBNET: Subnet<Ipv6Addr> =
786        Subnet { network: Ipv6Addr::new([0xff00, 0, 0, 0, 0, 0, 0, 0]), prefix: 8 };
787    /// The subnet of link-local unicast addresses, defined in [RFC 4291 Section
788    /// 2.4].
789    ///
790    /// Note that multicast addresses can also be link-local. However, there is
791    /// no single subnet of link-local multicast addresses. For more details on
792    /// link-local multicast addresses, see [RFC 4291 Section 2.7].
793    ///
794    /// [RFC 4291 Section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
795    /// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
796    const LINK_LOCAL_UNICAST_SUBNET: Subnet<Ipv6Addr> =
797        Subnet { network: Ipv6Addr::new([0xfe80, 0, 0, 0, 0, 0, 0, 0]), prefix: 10 };
798    const NAME: &'static str = "IPv6";
799    /// The IPv6 minimum link MTU, defined in [RFC 8200 Section 5].
800    ///
801    /// Per RFC 8200:
802    ///
803    /// > IPv6 requires that every link in the Internet have an MTU of 1280
804    /// > octets or greater. This is known as the IPv6 minimum link MTU. On any
805    /// > link that cannot convey a 1280-octet packet in one piece, link-
806    /// > specific fragmentation and reassembly must be provided at a layer
807    /// > below IPv6.
808    ///
809    /// [RFC 8200 Section 5]: https://tools.ietf.org/html/rfc8200#section-5
810    const MINIMUM_LINK_MTU: Mtu = Mtu(1280);
811    type Addr = Ipv6Addr;
812
813    fn map_ip<
814        In: GenericOverIp<Self, Type = In> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
815        Out: GenericOverIp<Self, Type = Out> + GenericOverIp<Ipv4> + GenericOverIp<Ipv6>,
816    >(
817        input: In,
818        _v4: impl FnOnce(<In as GenericOverIp<Ipv4>>::Type) -> <Out as GenericOverIp<Ipv4>>::Type,
819        v6: impl FnOnce(<In as GenericOverIp<Ipv6>>::Type) -> <Out as GenericOverIp<Ipv6>>::Type,
820    ) -> Out {
821        v6(input)
822    }
823}
824
825impl Ipv6 {
826    /// The loopback address represented as a [`UnicastAddr`].
827    ///
828    /// This is equivalent to [`LOOPBACK_ADDRESS`], except that it is a
829    /// [`UnicastAddr`] witness type.
830    ///
831    /// [`LOOPBACK_ADDRESS`]: Ipv6::LOOPBACK_ADDRESS
832    pub const LOOPBACK_IPV6_ADDRESS: UnicastAddr<Ipv6Addr> =
833        unsafe { UnicastAddr::new_unchecked(Ipv6::LOOPBACK_ADDRESS.0) };
834
835    /// The IPv6 All Nodes multicast address in link-local scope, defined in
836    /// [RFC 4291 Section 2.7.1].
837    ///
838    /// [RFC 4291 Section 2.7.1]: https://tools.ietf.org/html/rfc4291#section-2.7.1
839    pub const ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS: MulticastAddr<Ipv6Addr> =
840        unsafe { MulticastAddr::new_unchecked(Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0, 0, 1])) };
841
842    /// The IPv6 All Routers multicast address in link-local scope, defined in
843    /// [RFC 4291 Section 2.7.1].
844    ///
845    /// [RFC 4291 Section 2.7.1]: https://tools.ietf.org/html/rfc4291#section-2.7.1
846    pub const ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS: MulticastAddr<Ipv6Addr> =
847        unsafe { MulticastAddr::new_unchecked(Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0, 0, 2])) };
848
849    /// The (deprecated) subnet of site-local unicast addresses, defined in [RFC
850    /// 3513 Section 2.5.6].
851    ///
852    /// The site-local unicast subnet was deprecated in [RFC 3879]:
853    ///
854    /// > The special behavior of this prefix MUST no longer be supported in new
855    /// > implementations. The prefix MUST NOT be reassigned for other use
856    /// > except by a future IETF standards action... However, router
857    /// > implementations SHOULD be configured to prevent routing of this prefix
858    /// > by default.
859    ///
860    /// [RFC 3513 Section 2.5.6]: https://tools.ietf.org/html/rfc3513#section-2.5.6
861    /// [RFC 3879]: https://tools.ietf.org/html/rfc3879
862    pub const SITE_LOCAL_UNICAST_SUBNET: Subnet<Ipv6Addr> =
863        Subnet { network: Ipv6Addr::new([0xfec0, 0, 0, 0, 0, 0, 0, 0]), prefix: 10 };
864
865    /// The length, in bits, of the interface identifier portion of unicast IPv6
866    /// addresses *except* for addresses which start with the binary value 000.
867    ///
868    /// According to [RFC 4291 Section 2.5.1], "\[f\]or all unicast addresses,
869    /// except those that start with the binary value 000, Interface IDs are
870    /// required to be 64 bits."
871    ///
872    /// Note that, per [RFC 4862 Section 5.5.3]:
873    ///
874    /// > a future revision of the address architecture \[RFC4291\] and a future
875    /// > link-type-specific document, which will still be consistent with each
876    /// > other, could potentially allow for an interface identifier of length
877    /// > other than the value defined in the current documents.  Thus, an
878    /// > implementation should not assume a particular constant.  Rather, it
879    /// > should expect any lengths of interface identifiers.
880    ///
881    /// In other words, this constant may be used to generate addresses or
882    /// subnet prefix lengths, but should *not* be used to validate addresses or
883    /// subnet prefix lengths generated by other software or other machines, as
884    /// it might be valid for other software or other machines to use an
885    /// interface identifier length different from this one.
886    ///
887    /// [RFC 4291 Section 2.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.1
888    /// [RFC 4862 Section 5.5.3]: https://tools.ietf.org/html/rfc4862#section-5.5.3
889    pub const UNICAST_INTERFACE_IDENTIFIER_BITS: u8 = 64;
890
891    /// The length, in bits, of an IPv6 flow label, defined in [RFC 6437 Section 2].
892    ///
893    /// [RFC 6437 Section 2]: https://tools.ietf.org/html/rfc6437#section-2
894    pub const FLOW_LABEL_BITS: u8 = 20;
895}
896
897/// An IPv4 or IPv6 address.
898///
899/// `IpAddress` is implemented by [`Ipv4Addr`] and [`Ipv6Addr`]. It is sealed,
900/// and there are guaranteed to be no other implementors besides these. Code -
901/// including unsafe code - may rely on this assumption for its correctness and
902/// soundness.
903pub trait IpAddress:
904    Sized
905    + Eq
906    + PartialEq
907    + PartialOrd
908    + Ord
909    + Hash
910    + Copy
911    + Display
912    + Debug
913    + Default
914    + Sync
915    + Send
916    + LinkLocalAddress
917    + ScopeableAddress
918    + GenericOverIp<Self::Version, Type = Self>
919    + GenericOverIp<Ipv4, Type = Ipv4Addr>
920    + GenericOverIp<Ipv6, Type = Ipv6Addr>
921    + sealed::Sealed
922    + 'static
923{
924    /// The number of bytes in an address of this type.
925    ///
926    /// 4 for IPv4 and 16 for IPv6.
927    const BYTES: u8;
928
929    /// The IP version type of this address.
930    ///
931    /// [`Ipv4`] for [`Ipv4Addr`] and [`Ipv6`] for [`Ipv6Addr`].
932    type Version: Ip<Addr = Self>;
933
934    /// Gets the underlying bytes of the address.
935    fn bytes(&self) -> &[u8];
936
937    /// Masks off the top bits of the address.
938    ///
939    /// Returns a copy of `self` where all but the top `bits` bits are set to
940    /// 0.
941    ///
942    /// # Panics
943    ///
944    /// `mask` panics if `bits` is out of range - if it is greater than 32 for
945    /// IPv4 or greater than 128 for IPv6.
946    fn mask(&self, bits: u8) -> Self;
947
948    /// Converts a statically-typed IP address into a dynamically-typed one.
949    fn to_ip_addr(&self) -> IpAddr;
950
951    /// Is this a loopback address?
952    ///
953    /// `is_loopback` returns `true` if this address is a member of the
954    /// [`LOOPBACK_SUBNET`].
955    ///
956    /// [`LOOPBACK_SUBNET`]: Ip::LOOPBACK_SUBNET
957    #[inline]
958    fn is_loopback(&self) -> bool {
959        Self::Version::LOOPBACK_SUBNET.contains(self)
960    }
961
962    /// Calculates the common prefix length between this address and `other`.
963    fn common_prefix_len(&self, other: &Self) -> u8;
964
965    /// Is this a unicast address contained in the given subnet?
966    ///
967    /// `is_unicast_in_subnet` returns `true` if the given subnet contains this
968    /// address and the address is none of:
969    /// - a multicast address
970    /// - the IPv4 limited broadcast address
971    /// - the IPv4 subnet-specific broadcast address for the given subnet
972    /// - an IPv4 address whose host bits (those bits following the network
973    ///   prefix) are all 0
974    /// - the unspecified address
975    /// - an IPv4 Class E address
976    ///
977    /// Note two exceptions to these rules: If `subnet` is an IPv4 /32, then the
978    /// single unicast address in the subnet is also technically the subnet
979    /// broadcast address. If `subnet` is an IPv4 /31, then both addresses in
980    /// that subnet are broadcast addresses. In either case, the "no
981    /// subnet-specific broadcast" and "no address with a host part of all
982    /// zeroes" rules don't apply. Note further that this exception *doesn't*
983    /// apply to the unspecified address, which is never considered a unicast
984    /// address regardless of what subnet it's in.
985    ///
986    /// # RFC Deep Dive
987    ///
988    /// ## IPv4 addresses ending in zeroes
989    ///
990    /// In this section, we justify the rule that IPv4 addresses whose host bits
991    /// are all 0 are not considered unicast addresses.
992    ///
993    /// In earlier standards, an IPv4 address whose bits were all 0 after the
994    /// network prefix (e.g., 192.168.0.0 in the subnet 192.168.0.0/16) were a
995    /// form of "network-prefix-directed" broadcast addresses. Similarly,
996    /// 0.0.0.0 was considered a form of "limited broadcast address" (equivalent
997    /// to 255.255.255.255). These have since been deprecated (in the case of
998    /// 0.0.0.0, it is now considered the "unspecified" address).
999    ///
1000    /// As evidence that this deprecation is official, consider [RFC 1812
1001    /// Section 5.3.5]. In reference to these types of addresses, it states that
1002    /// "packets addressed to any of these addresses SHOULD be silently
1003    /// discarded \[by routers\]". This not only deprecates them as broadcast
1004    /// addresses, but also as unicast addresses (after all, unicast addresses
1005    /// are not particularly useful if packets destined to them are discarded by
1006    /// routers).
1007    ///
1008    /// ## IPv4 /31 and /32 exceptions
1009    ///
1010    /// In this section, we justify the exceptions that all addresses in IPv4
1011    /// /31 and /32 subnets are considered unicast.
1012    ///
1013    /// For /31 subnets, the case is easy. [RFC 3021 Section 2.1] states that
1014    /// both addresses in a /31 subnet "MUST be interpreted as host addresses."
1015    ///
1016    /// For /32, the case is a bit more vague. RFC 3021 makes no mention of /32
1017    /// subnets. However, the same reasoning applies - if an exception is not
1018    /// made, then there do not exist any host addresses in a /32 subnet. [RFC
1019    /// 4632 Section 3.1] also vaguely implies this interpretation by referring
1020    /// to addresses in /32 subnets as "host routes."
1021    ///
1022    /// [RFC 1812 Section 5.3.5]: https://tools.ietf.org/html/rfc1812#page-92
1023    /// [RFC 4632 Section 3.1]: https://tools.ietf.org/html/rfc4632#section-3.1
1024    fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool;
1025
1026    // Functions used to implement internal types. These functions aren't
1027    // particularly useful to users, but allow us to implement certain
1028    // specialization-like behavior without actually relying on the unstable
1029    // `specialization` feature.
1030
1031    #[doc(hidden)]
1032    fn subnet_into_either(subnet: Subnet<Self>) -> SubnetEither;
1033
1034    #[doc(hidden)]
1035    fn array_into_ip_addr<const N: usize>(addrs: [Self; N])
1036        -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]>;
1037}
1038
1039impl<A: IpAddress> SpecifiedAddress for A {
1040    /// Is this an address other than the unspecified address?
1041    ///
1042    /// `is_specified` returns true if `self` is not equal to
1043    /// [`A::Version::UNSPECIFIED_ADDRESS`].
1044    ///
1045    /// [`A::Version::UNSPECIFIED_ADDRESS`]: Ip::UNSPECIFIED_ADDRESS
1046    #[inline]
1047    fn is_specified(&self) -> bool {
1048        self != &A::Version::UNSPECIFIED_ADDRESS
1049    }
1050}
1051
1052/// Maps a method over an `IpAddr`, calling it after matching on the type of IP
1053/// address.
1054macro_rules! map_ip_addr {
1055    ($val:expr, $method:ident) => {
1056        match $val {
1057            IpAddr::V4(a) => a.$method(),
1058            IpAddr::V6(a) => a.$method(),
1059        }
1060    };
1061}
1062
1063impl SpecifiedAddress for IpAddr {
1064    /// Is this an address other than the unspecified address?
1065    ///
1066    /// `is_specified` returns true if `self` is not equal to
1067    /// [`Ip::UNSPECIFIED_ADDRESS`] for the IP version of this address.
1068    #[inline]
1069    fn is_specified(&self) -> bool {
1070        map_ip_addr!(self, is_specified)
1071    }
1072}
1073
1074impl<A: IpAddress> MulticastAddress for A {
1075    /// Is this address in the multicast subnet?
1076    ///
1077    /// `is_multicast` returns true if `self` is in
1078    /// [`A::Version::MULTICAST_SUBNET`].
1079    ///
1080    /// [`A::Version::MULTICAST_SUBNET`]: Ip::MULTICAST_SUBNET
1081    #[inline]
1082    fn is_multicast(&self) -> bool {
1083        <A as IpAddress>::Version::MULTICAST_SUBNET.contains(self)
1084    }
1085}
1086
1087impl MulticastAddress for IpAddr {
1088    /// Is this an address in the multicast subnet?
1089    ///
1090    /// `is_multicast` returns true if `self` is in [`Ip::MULTICAST_SUBNET`] for
1091    /// the IP version of this address.
1092    #[inline]
1093    fn is_multicast(&self) -> bool {
1094        map_ip_addr!(self, is_multicast)
1095    }
1096}
1097
1098impl LinkLocalAddress for Ipv4Addr {
1099    /// Is this address in the link-local subnet?
1100    ///
1101    /// `is_link_local` returns true if `self` is in
1102    /// [`Ipv4::LINK_LOCAL_UNICAST_SUBNET`] or
1103    /// [`Ipv4::LINK_LOCAL_MULTICAST_SUBNET`].
1104    #[inline]
1105    fn is_link_local(&self) -> bool {
1106        Ipv4::LINK_LOCAL_UNICAST_SUBNET.contains(self)
1107            || Ipv4::LINK_LOCAL_MULTICAST_SUBNET.contains(self)
1108    }
1109}
1110
1111impl LinkLocalAddress for Ipv6Addr {
1112    /// Is this address in the link-local subnet?
1113    ///
1114    /// `is_link_local` returns true if `self` is in
1115    /// [`Ipv6::LINK_LOCAL_UNICAST_SUBNET`], is a multicast address whose scope
1116    /// is link-local, or is the address [`Ipv6::LOOPBACK_ADDRESS`] (per [RFC
1117    /// 4291 Section 2.5.3], the loopback address is considered to have
1118    /// link-local scope).
1119    ///
1120    /// [RFC 4291 Section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
1121    #[inline]
1122    fn is_link_local(&self) -> bool {
1123        Ipv6::LINK_LOCAL_UNICAST_SUBNET.contains(self)
1124            || (self.is_multicast() && self.scope() == Ipv6Scope::LinkLocal)
1125            || self == Ipv6::LOOPBACK_ADDRESS.deref()
1126    }
1127}
1128
1129impl LinkLocalAddress for IpAddr {
1130    /// Is this address link-local?
1131    #[inline]
1132    fn is_link_local(&self) -> bool {
1133        map_ip_addr!(self, is_link_local)
1134    }
1135}
1136
1137impl<A: IpAddress> MappedAddress for A {
1138    /// Is this address non-mapped?
1139    ///
1140    /// For IPv4 addresses, this always returns true because they do not have a
1141    /// mapped address space.
1142    ///
1143    /// For Ipv6 addresses, this returns true if `self` is outside of the IPv4
1144    /// mapped Ipv6 address subnet, as defined in [RFC 4291 Section 2.5.5.2]
1145    /// (e.g. `::FFFF:0:0/96`).
1146    ///
1147    /// [RFC 4291 Section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
1148    #[inline]
1149    fn is_non_mapped(&self) -> bool {
1150        A::Version::map_ip(self, |_addr_v4| true, |addr_v6| addr_v6.to_ipv4_mapped().is_none())
1151    }
1152}
1153
1154impl MappedAddress for IpAddr {
1155    /// Is this address non-mapped?
1156    #[inline]
1157    fn is_non_mapped(&self) -> bool {
1158        map_ip_addr!(self, is_non_mapped)
1159    }
1160}
1161
1162impl<I: Ip> GenericOverIp<I> for Ipv4Addr {
1163    type Type = I::Addr;
1164}
1165
1166impl<I: Ip> GenericOverIp<I> for Ipv6Addr {
1167    type Type = I::Addr;
1168}
1169
1170impl ScopeableAddress for Ipv4Addr {
1171    type Scope = ();
1172
1173    /// The scope of this address.
1174    ///
1175    /// Although IPv4 defines a link local subnet, IPv4 addresses are always
1176    /// considered to be in the global scope.
1177    fn scope(&self) {}
1178}
1179
1180/// The list of IPv6 scopes.
1181///
1182/// These scopes are defined by [RFC 4291 Section 2.7].
1183///
1184/// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1185#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1186pub enum Ipv6Scope {
1187    /// The interface-local scope.
1188    InterfaceLocal,
1189    /// The link-local scope.
1190    LinkLocal,
1191    /// The admin-local scope.
1192    AdminLocal,
1193    /// The (deprecated) site-local scope.
1194    ///
1195    /// The site-local scope was deprecated in [RFC 3879]. While this scope
1196    /// is returned for both site-local unicast and site-local multicast
1197    /// addresses, RFC 3879 says the following about site-local unicast addresses
1198    /// in particular ("this prefix" refers to the [site-local unicast subnet]):
1199    ///
1200    /// > The special behavior of this prefix MUST no longer be supported in new
1201    /// > implementations. The prefix MUST NOT be reassigned for other use
1202    /// > except by a future IETF standards action... However, router
1203    /// > implementations SHOULD be configured to prevent routing of this prefix
1204    /// > by default.
1205    ///
1206    /// [RFC 3879]: https://tools.ietf.org/html/rfc3879
1207    /// [site-local unicast subnet]: Ipv6::SITE_LOCAL_UNICAST_SUBNET
1208    SiteLocal,
1209    /// The organization-local scope.
1210    OrganizationLocal,
1211    /// The global scope.
1212    Global,
1213    /// Scopes which are reserved for future use by [RFC 4291 Section 2.7].
1214    ///
1215    /// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1216    Reserved(Ipv6ReservedScope),
1217    /// Scopes which are available for local definition by administrators.
1218    Unassigned(Ipv6UnassignedScope),
1219}
1220
1221/// The list of IPv6 scopes which are reserved for future use by [RFC 4291
1222/// Section 2.7].
1223///
1224/// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1225#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1226pub enum Ipv6ReservedScope {
1227    /// The scope with numerical value 0.
1228    Scope0 = 0,
1229    /// The scope with numerical value 3.
1230    Scope3 = 3,
1231    /// The scope with numerical value 0xF.
1232    ScopeF = 0xF,
1233}
1234
1235/// The list of IPv6 scopes which are available for local definition by
1236/// administrators.
1237#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1238pub enum Ipv6UnassignedScope {
1239    /// The scope with numerical value 6.
1240    Scope6 = 6,
1241    /// The scope with numerical value 7.
1242    Scope7 = 7,
1243    /// The scope with numerical value 9.
1244    Scope9 = 9,
1245    /// The scope with numerical value 0xA.
1246    ScopeA = 0xA,
1247    /// The scope with numerical value 0xB.
1248    ScopeB = 0xB,
1249    /// The scope with numerical value 0xC.
1250    ScopeC = 0xC,
1251    /// The scope with numerical value 0xD.
1252    ScopeD = 0xD,
1253}
1254
1255impl Scope for Ipv6Scope {
1256    #[inline]
1257    fn can_have_zone(&self) -> bool {
1258        // Per RFC 6874 Section 4:
1259        //
1260        // > [I]mplementations MUST NOT allow use of this format except for
1261        // > well-defined usages, such as sending to link-local addresses under
1262        // > prefix fe80::/10.  At the time of writing, this is the only
1263        // > well-defined usage known.
1264        //
1265        // While this directive applies particularly to the human-readable
1266        // string representation of IPv6 addresses and zone identifiers, it
1267        // seems reasonable to limit the in-memory representation in the same
1268        // way.
1269        //
1270        // Note that, if interpreted literally, this quote would bar the use of
1271        // zone identifiers on link-local multicast addresses (they are not
1272        // under the prefix fe80::/10). However, it seems clear that this is not
1273        // the interpretation that was intended. Link-local multicast addresses
1274        // have the same need for a zone identifier as link-local unicast
1275        // addresses, and indeed, real systems like Linux allow link-local
1276        // multicast addresses to be accompanied by zone identifiers.
1277        matches!(self, Ipv6Scope::LinkLocal)
1278    }
1279}
1280
1281impl Ipv6Scope {
1282    /// The multicast scope ID of an interface-local address, defined in [RFC
1283    /// 4291 Section 2.7].
1284    ///
1285    /// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1286    pub const MULTICAST_SCOPE_ID_INTERFACE_LOCAL: u8 = 1;
1287
1288    /// The multicast scope ID of a link-local address, defined in [RFC 4291
1289    /// Section 2.7].
1290    ///
1291    /// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1292    pub const MULTICAST_SCOPE_ID_LINK_LOCAL: u8 = 2;
1293
1294    /// The multicast scope ID of an admin-local address, defined in [RFC 4291
1295    /// Section 2.7].
1296    ///
1297    /// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1298    pub const MULTICAST_SCOPE_ID_ADMIN_LOCAL: u8 = 4;
1299
1300    /// The multicast scope ID of a (deprecated) site-local address, defined in
1301    /// [RFC 4291 Section 2.7].
1302    ///
1303    /// Note that site-local addresses are deprecated.
1304    ///
1305    /// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1306    pub const MULTICAST_SCOPE_ID_SITE_LOCAL: u8 = 5;
1307
1308    /// The multicast scope ID of an organization-local address, defined in [RFC
1309    /// 4291 Section 2.7].
1310    ///
1311    /// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1312    pub const MULTICAST_SCOPE_ID_ORG_LOCAL: u8 = 8;
1313
1314    /// The multicast scope ID of global address, defined in [RFC 4291 Section
1315    /// 2.7].
1316    ///
1317    /// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1318    pub const MULTICAST_SCOPE_ID_GLOBAL: u8 = 0xE;
1319
1320    /// The ID used to indicate this scope in a multicast IPv6 address.
1321    ///
1322    /// Per [RFC 4291 Section 2.7], the bits of a multicast IPv6 address are
1323    /// laid out as follows:
1324    ///
1325    /// ```text
1326    /// |   8    |  4 |  4 |                  112 bits                   |
1327    /// +------ -+----+----+---------------------------------------------+
1328    /// |11111111|flgs|scop|                  group ID                   |
1329    /// +--------+----+----+---------------------------------------------+
1330    /// ```
1331    ///
1332    /// The 4-bit scop field encodes the scope of the address.
1333    /// `multicast_scope_id` returns the numerical value used to encode this
1334    /// scope in the scop field of a multicast address.
1335    ///
1336    /// [RFC 4291 Section 2.7]: https://tools.ietf.org/html/rfc4291#section-2.7
1337    pub fn multicast_scope_id(&self) -> u8 {
1338        match self {
1339            Ipv6Scope::Reserved(Ipv6ReservedScope::Scope0) => 0,
1340            Ipv6Scope::InterfaceLocal => Self::MULTICAST_SCOPE_ID_INTERFACE_LOCAL,
1341            Ipv6Scope::LinkLocal => Self::MULTICAST_SCOPE_ID_LINK_LOCAL,
1342            Ipv6Scope::Reserved(Ipv6ReservedScope::Scope3) => 3,
1343            Ipv6Scope::AdminLocal => Self::MULTICAST_SCOPE_ID_ADMIN_LOCAL,
1344            Ipv6Scope::SiteLocal => Self::MULTICAST_SCOPE_ID_SITE_LOCAL,
1345            Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope6) => 6,
1346            Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope7) => 7,
1347            Ipv6Scope::OrganizationLocal => Self::MULTICAST_SCOPE_ID_ORG_LOCAL,
1348            Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope9) => 9,
1349            Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeA) => 0xA,
1350            Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeB) => 0xB,
1351            Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeC) => 0xC,
1352            Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeD) => 0xD,
1353            Ipv6Scope::Global => Self::MULTICAST_SCOPE_ID_GLOBAL,
1354            Ipv6Scope::Reserved(Ipv6ReservedScope::ScopeF) => 0xF,
1355        }
1356    }
1357}
1358
1359impl ScopeableAddress for Ipv6Addr {
1360    type Scope = Ipv6Scope;
1361
1362    /// The scope of this address.
1363    #[inline]
1364    fn scope(&self) -> Ipv6Scope {
1365        if self.is_multicast() {
1366            use Ipv6ReservedScope::*;
1367            use Ipv6Scope::*;
1368            use Ipv6UnassignedScope::*;
1369
1370            // The "scop" field of a multicast address is the last 4 bits of the
1371            // second byte of the address (see
1372            // https://tools.ietf.org/html/rfc4291#section-2.7).
1373            match self.0[1] & 0xF {
1374                0 => Reserved(Scope0),
1375                Ipv6Scope::MULTICAST_SCOPE_ID_INTERFACE_LOCAL => InterfaceLocal,
1376                Ipv6Scope::MULTICAST_SCOPE_ID_LINK_LOCAL => LinkLocal,
1377                3 => Reserved(Scope3),
1378                Ipv6Scope::MULTICAST_SCOPE_ID_ADMIN_LOCAL => AdminLocal,
1379                Ipv6Scope::MULTICAST_SCOPE_ID_SITE_LOCAL => SiteLocal,
1380                6 => Unassigned(Scope6),
1381                7 => Unassigned(Scope7),
1382                Ipv6Scope::MULTICAST_SCOPE_ID_ORG_LOCAL => OrganizationLocal,
1383                9 => Unassigned(Scope9),
1384                0xA => Unassigned(ScopeA),
1385                0xB => Unassigned(ScopeB),
1386                0xC => Unassigned(ScopeC),
1387                0xD => Unassigned(ScopeD),
1388                Ipv6Scope::MULTICAST_SCOPE_ID_GLOBAL => Global,
1389                0xF => Reserved(ScopeF),
1390                _ => unreachable!(),
1391            }
1392        } else if self.is_link_local() {
1393            Ipv6Scope::LinkLocal
1394        } else if self.is_site_local() {
1395            Ipv6Scope::SiteLocal
1396        } else {
1397            Ipv6Scope::Global
1398        }
1399    }
1400}
1401
1402impl Scope for IpAddr<(), Ipv6Scope> {
1403    #[inline]
1404    fn can_have_zone(&self) -> bool {
1405        match self {
1406            IpAddr::V4(scope) => scope.can_have_zone(),
1407            IpAddr::V6(scope) => scope.can_have_zone(),
1408        }
1409    }
1410}
1411
1412impl ScopeableAddress for IpAddr {
1413    type Scope = IpAddr<(), Ipv6Scope>;
1414
1415    #[inline]
1416    fn scope(&self) -> IpAddr<(), Ipv6Scope> {
1417        match self {
1418            IpAddr::V4(_) => IpAddr::V4(()),
1419            IpAddr::V6(addr) => IpAddr::V6(addr.scope()),
1420        }
1421    }
1422}
1423
1424// The definition of each trait for `IpAddr` is equal to the definition of that
1425// trait for whichever of `Ipv4Addr` and `Ipv6Addr` is actually present in the
1426// enum. Thus, we can convert between `$witness<IpvXAddr>`, `$witness<IpAddr>`,
1427// and `IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>` arbitrarily.
1428
1429/// Provides various useful `From` impls for an IP address witness type.
1430///
1431/// `impl_from_witness!($witness)` implements:
1432/// - `From<IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>> for
1433///   $witness<IpAddr>`
1434/// - `From<$witness<IpAddr>> for IpAddr<$witness<Ipv4Addr>,
1435///   $witness<Ipv6Addr>>`
1436/// - `From<$witness<A>> for $witness<A>`
1437/// - `From<$witness<Ipv4Addr>> for IpAddr`
1438/// - `From<$witness<Ipv6Addr>> for IpAddr`
1439/// - `TryFrom<Ipv4Addr> for $witness<Ipv4Addr>`
1440/// - `TryFrom<Ipv6Addr> for $witness<Ipv6Addr>`
1441///
1442/// `impl_from_witness!($witness, $ipaddr, $new_unchecked)` implements:
1443/// - `From<$witness<$ipaddr>> for $witness<IpAddr>`
1444/// - `From<$witness<$ipaddr>> for $ipaddr`
1445/// - `TryFrom<$ipaddr> for $witness<$ipaddr>`
1446macro_rules! impl_from_witness {
1447    ($witness:ident, $witness_trait:ident) => {
1448        impl From<IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>> for $witness<IpAddr> {
1449            fn from(addr: IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>>) -> $witness<IpAddr> {
1450                unsafe {
1451                    Witness::new_unchecked(match addr {
1452                        IpAddr::V4(addr) => IpAddr::V4(addr.get()),
1453                        IpAddr::V6(addr) => IpAddr::V6(addr.get()),
1454                    })
1455                }
1456            }
1457        }
1458        impl From<$witness<IpAddr>> for IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1459            fn from(addr: $witness<IpAddr>) -> IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1460                unsafe {
1461                    match addr.get() {
1462                        IpAddr::V4(addr) => IpAddr::V4(Witness::new_unchecked(addr)),
1463                        IpAddr::V6(addr) => IpAddr::V6(Witness::new_unchecked(addr)),
1464                    }
1465                }
1466            }
1467        }
1468        impl<A: IpAddress> From<$witness<A>> for $witness<IpAddr> {
1469            fn from(addr: $witness<A>) -> $witness<IpAddr> {
1470                unsafe { Witness::new_unchecked(addr.to_ip_addr()) }
1471            }
1472        }
1473        impl<A: IpAddress> From<$witness<A>> for IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1474            fn from(addr: $witness<A>) -> IpAddr<$witness<Ipv4Addr>, $witness<Ipv6Addr>> {
1475                let addr: $witness<IpAddr> = addr.into();
1476                addr.into()
1477            }
1478        }
1479        // NOTE: Orphan rules prevent implementing `From` for `A: IpAddress`.
1480        impl<A: Into<Ipv4Addr> + $witness_trait + Copy> From<$witness<A>> for Ipv4Addr {
1481            fn from(addr: $witness<A>) -> Ipv4Addr {
1482                let addr: A = addr.get();
1483                addr.into()
1484            }
1485        }
1486        impl<A: Into<Ipv6Addr> + $witness_trait + Copy> From<$witness<A>> for Ipv6Addr {
1487            fn from(addr: $witness<A>) -> Ipv6Addr {
1488                let addr: A = addr.get();
1489                addr.into()
1490            }
1491        }
1492        // NOTE: Orphan rules prevent implementing `TryFrom` for `A: IpAddress`.
1493        impl TryFrom<Ipv4Addr> for $witness<Ipv4Addr> {
1494            type Error = ();
1495            fn try_from(addr: Ipv4Addr) -> Result<$witness<Ipv4Addr>, ()> {
1496                Witness::new(addr).ok_or(())
1497            }
1498        }
1499        impl TryFrom<Ipv6Addr> for $witness<Ipv6Addr> {
1500            type Error = ();
1501            fn try_from(addr: Ipv6Addr) -> Result<$witness<Ipv6Addr>, ()> {
1502                Witness::new(addr).ok_or(())
1503            }
1504        }
1505    };
1506    ($witness:ident, $witness_trait:ident, $ipaddr:ident, $new_unchecked:expr) => {
1507        impl From<$witness<$ipaddr>> for $witness<IpAddr> {
1508            fn from(addr: $witness<$ipaddr>) -> $witness<IpAddr> {
1509                let addr: $ipaddr = addr.get();
1510                let addr: IpAddr = addr.into();
1511                #[allow(unused_unsafe)] // For when a closure is passed
1512                unsafe {
1513                    $new_unchecked(addr)
1514                }
1515            }
1516        }
1517        impl<A: Into<$ipaddr> + $witness_trait + Copy> From<$witness<A>> for $ipaddr {
1518            fn from(addr: $witness<A>) -> $ipaddr {
1519                let addr: A = addr.get();
1520                addr.into()
1521            }
1522        }
1523        impl TryFrom<$ipaddr> for $witness<$ipaddr> {
1524            type Error = ();
1525            fn try_from(addr: $ipaddr) -> Result<$witness<$ipaddr>, ()> {
1526                Witness::new(addr).ok_or(())
1527            }
1528        }
1529    };
1530}
1531
1532impl_from_witness!(SpecifiedAddr, SpecifiedAddress);
1533impl_from_witness!(MulticastAddr, MulticastAddress);
1534impl_from_witness!(LinkLocalAddr, LinkLocalAddress);
1535impl_from_witness!(NonMappedAddr, MappedAddress);
1536// Only add `From` conversions for `Ipv6Addr`, because `Ipv4Addr` does not
1537// implement `UnicastAddress`.
1538impl_from_witness!(UnicastAddr, UnicastAddress, Ipv6Addr, UnicastAddr::new_unchecked);
1539
1540/// The class of an IPv4 address.
1541///
1542/// The classful addressing scheme is obsoloted in favour of [CIDR] but is still
1543/// used on some systems. For more information, see [RFC 791 section 2.3] and
1544/// [RFC 1812 section 2.2.5.1].
1545///
1546/// [CIDR]: https://datatracker.ietf.org/doc/html/rfc1518
1547/// [RFC 791 section 2.3]: https://datatracker.ietf.org/doc/html/rfc791#section-2.3
1548/// [RFC 1812 section 2.2.5.1]: https://datatracker.ietf.org/doc/html/rfc1812#section-2.2.5.1
1549#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1550pub enum Ipv4AddressClass {
1551    /// A Class A IPv4 address.
1552    A,
1553    /// A Class B IPv4 address.
1554    B,
1555    /// A Class C IPv4 address.
1556    C,
1557    /// A Class D IPv4 address.
1558    ///
1559    /// Class D addresses are also known as multicast.
1560    D,
1561    /// A Class E IPv4 address.
1562    ///
1563    /// Class E addresses are also known as experimental.
1564    E,
1565}
1566
1567impl Ipv4AddressClass {
1568    /// Returns the default prefix length for an IPv4 address class if the
1569    /// prefix is well-defined.
1570    pub const fn default_prefix_len(self) -> Option<u8> {
1571        // Per RFC 943 https://datatracker.ietf.org/doc/html/rfc943
1572        //
1573        //   The first type of address, or class A, has a 7-bit network number
1574        //   and a 24-bit local address.  The highest-order bit is set to 0.
1575        //   This allows 128 class A networks.
1576        //
1577        //                        1                   2                   3
1578        //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1579        //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1580        //   |0|   NETWORK   |                Local Address                  |
1581        //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1582        //
1583        //                          Class A Address
1584        //
1585        //   The second type of address, class B, has a 14-bit network number
1586        //   and a 16-bit local address.  The two highest-order bits are set to
1587        //   1-0.  This allows 16,384 class B networks.
1588        //
1589        //                        1                   2                   3
1590        //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1591        //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1592        //   |1 0|           NETWORK         |          Local Address        |
1593        //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1594        //
1595        //                          Class B Address
1596        //
1597        //   The third type of address, class C, has a 21-bit network number
1598        //   and a 8-bit local address.  The three highest-order bits are set
1599        //   to 1-1-0.  This allows 2,097,152 class C networks.
1600        //
1601        //                        1                   2                   3
1602        //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1603        //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1604        //   |1 1 0|                    NETWORK              | Local Address |
1605        //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1606        //
1607        //                          Class C Address
1608        match self {
1609            Ipv4AddressClass::A => Some(8),
1610            Ipv4AddressClass::B => Some(16),
1611            Ipv4AddressClass::C => Some(24),
1612            Ipv4AddressClass::D => None,
1613            Ipv4AddressClass::E => None,
1614        }
1615    }
1616}
1617
1618/// An IPv4 address.
1619///
1620/// # Layout
1621///
1622/// `Ipv4Addr` has the same layout as `[u8; 4]`, which is the layout that most
1623/// protocols use to represent an IPv4 address in their packet formats. This can
1624/// be useful when parsing an IPv4 address from a packet. For example:
1625///
1626/// ```rust
1627/// # use net_types::ip::Ipv4Addr;
1628/// /// An ICMPv4 Redirect Message header.
1629/// ///
1630/// /// `Icmpv4RedirectHeader` has the same layout as the header of an ICMPv4
1631/// /// Redirect Message.
1632/// #[repr(C)]
1633/// struct Icmpv4RedirectHeader {
1634///     typ: u8,
1635///     code: u8,
1636///     checksum: [u8; 2],
1637///     gateway: Ipv4Addr,
1638/// }
1639/// ```
1640#[derive(
1641    Copy,
1642    Clone,
1643    Default,
1644    PartialEq,
1645    Eq,
1646    PartialOrd,
1647    Ord,
1648    Hash,
1649    KnownLayout,
1650    FromBytes,
1651    IntoBytes,
1652    Immutable,
1653    Unaligned,
1654)]
1655#[repr(transparent)]
1656pub struct Ipv4Addr([u8; 4]);
1657
1658impl Ipv4Addr {
1659    /// Creates a new IPv4 address.
1660    #[inline]
1661    pub const fn new(bytes: [u8; 4]) -> Self {
1662        Ipv4Addr(bytes)
1663    }
1664
1665    /// Gets the bytes of the IPv4 address.
1666    #[inline]
1667    pub const fn ipv4_bytes(self) -> [u8; 4] {
1668        self.0
1669    }
1670
1671    /// Is this the limited broadcast address?
1672    ///
1673    /// `is_limited_broadcast` is a shorthand for comparing against
1674    /// [`Ipv4::LIMITED_BROADCAST_ADDRESS`].
1675    #[inline]
1676    pub fn is_limited_broadcast(self) -> bool {
1677        self == Ipv4::LIMITED_BROADCAST_ADDRESS.get()
1678    }
1679
1680    /// Is this a Class E address?
1681    ///
1682    /// `is_class_e` is a shorthand for checking membership in
1683    /// [`Ipv4::CLASS_E_SUBNET`].
1684    #[inline]
1685    pub fn is_class_e(self) -> bool {
1686        Ipv4::CLASS_E_SUBNET.contains(&self)
1687    }
1688
1689    /// Converts the address to an IPv4-compatible IPv6 address according to
1690    /// [RFC 4291 Section 2.5.5.1].
1691    ///
1692    /// IPv4-compatible IPv6 addresses were defined to assist in the IPv6
1693    /// transition, and are now specified in [RFC 4291 Section 2.5.5.1]. The
1694    /// lowest-order 32 bits carry an IPv4 address, while the highest-order 96
1695    /// bits are all set to 0 as in this diagram from the RFC:
1696    ///
1697    /// ```text
1698    /// |                80 bits               | 16 |      32 bits        |
1699    /// +--------------------------------------+--------------------------+
1700    /// |0000..............................0000|0000|    IPv4 address     |
1701    /// +--------------------------------------+----+---------------------+
1702    /// ```
1703    ///
1704    /// Per RFC 4291:
1705    ///
1706    /// > The 'IPv4-Compatible IPv6 address' is now deprecated because the
1707    /// > current IPv6 transition mechanisms no longer use these addresses. New
1708    /// > or updated implementations are not required to support this address
1709    /// > type.
1710    ///
1711    /// The more modern embedding format is IPv4-mapped IPv6 addressing - see
1712    /// [`to_ipv6_mapped`].
1713    ///
1714    /// [RFC 4291 Section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1
1715    /// [`to_ipv6_mapped`]: Ipv4Addr::to_ipv6_mapped
1716    #[inline]
1717    pub fn to_ipv6_compatible(self) -> Ipv6Addr {
1718        let Self([a, b, c, d]) = self;
1719        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
1720    }
1721
1722    /// Converts the address to an IPv4-mapped IPv6 address according to [RFC
1723    /// 4291 Section 2.5.5.2].
1724    ///
1725    /// IPv4-mapped IPv6 addresses are used to represent the addresses of IPv4
1726    /// nodes as IPv6 addresses, and are defined in [RFC 4291 Section 2.5.5.2].
1727    /// The lowest-order 32 bits carry an IPv4 address, the middle order 16 bits
1728    /// carry the literal 0xFFFF, and the highest order 80 bits are set to 0 as
1729    /// in this diagram from the RFC:
1730    ///
1731    /// ```text
1732    /// |                80 bits               | 16 |      32 bits        |
1733    /// +--------------------------------------+--------------------------+
1734    /// |0000..............................0000|FFFF|    IPv4 address     |
1735    /// +--------------------------------------+----+---------------------+
1736    /// ```
1737    ///
1738    /// [RFC 4291 Section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
1739    #[inline]
1740    pub fn to_ipv6_mapped(self) -> SpecifiedAddr<Ipv6Addr> {
1741        let Self([a, b, c, d]) = self;
1742        SpecifiedAddr::new(Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d]))
1743            .unwrap()
1744    }
1745
1746    /// Returns the address's class according to the obsoleted classful
1747    /// addressing architecture.
1748    pub fn class(&self) -> Ipv4AddressClass {
1749        for (subnet, class) in [
1750            (Ipv4::CLASS_A_SUBNET, Ipv4AddressClass::A),
1751            (Ipv4::CLASS_B_SUBNET, Ipv4AddressClass::B),
1752            (Ipv4::CLASS_C_SUBNET, Ipv4AddressClass::C),
1753            (Ipv4::CLASS_D_SUBNET, Ipv4AddressClass::D),
1754            (Ipv4::CLASS_E_SUBNET, Ipv4AddressClass::E),
1755        ] {
1756            if subnet.contains(self) {
1757                return class;
1758            }
1759        }
1760
1761        unreachable!("{} should fit into a class", self)
1762    }
1763}
1764
1765impl sealed::Sealed for Ipv4Addr {}
1766
1767impl IpAddress for Ipv4Addr {
1768    const BYTES: u8 = 4;
1769
1770    type Version = Ipv4;
1771
1772    #[inline]
1773    fn mask(&self, bits: u8) -> Self {
1774        assert!(bits <= 32);
1775        // Need to perform a checked shift left in case `bits == 32`, in which
1776        // case an unchecked shift left (`u32::MAX << bits`) would overflow,
1777        // causing a panic in debug mode.
1778        let mask = u32::MAX.checked_shl((32 - bits).into()).unwrap_or(0);
1779        Ipv4Addr((u32::from_be_bytes(self.0) & mask).to_be_bytes())
1780    }
1781
1782    #[inline]
1783    fn bytes(&self) -> &[u8] {
1784        &self.0
1785    }
1786
1787    #[inline]
1788    fn to_ip_addr(&self) -> IpAddr {
1789        IpAddr::V4(*self)
1790    }
1791
1792    #[inline]
1793    fn common_prefix_len(&self, other: &Ipv4Addr) -> u8 {
1794        let me = u32::from_be_bytes(self.0);
1795        let other = u32::from_be_bytes(other.0);
1796        // `same_bits` has a 0 wherever `me` and `other` have the same bit in a
1797        // given position, and a 1 wherever they have opposite bits.
1798        let same_bits = me ^ other;
1799        same_bits.leading_zeros() as u8
1800    }
1801
1802    #[inline]
1803    fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool {
1804        !self.is_multicast()
1805            && !self.is_limited_broadcast()
1806            // This clause implements the rules that (the subnet broadcast is
1807            // not unicast AND the address with an all-zeroes host part is not
1808            // unicast) UNLESS the prefix length is 31 or 32.
1809            && (subnet.prefix() == 32
1810            || subnet.prefix() == 31
1811            || (*self != subnet.broadcast() && *self != subnet.network()))
1812            && self.is_specified()
1813            && !self.is_class_e()
1814            && subnet.contains(self)
1815    }
1816
1817    fn subnet_into_either(subnet: Subnet<Ipv4Addr>) -> SubnetEither {
1818        SubnetEither::V4(subnet)
1819    }
1820
1821    #[inline]
1822    fn array_into_ip_addr<const N: usize>(
1823        addrs: [Self; N],
1824    ) -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
1825        IpAddr::V4(addrs)
1826    }
1827}
1828
1829impl From<[u8; 4]> for Ipv4Addr {
1830    #[inline]
1831    fn from(bytes: [u8; 4]) -> Ipv4Addr {
1832        Ipv4Addr(bytes)
1833    }
1834}
1835
1836#[cfg(feature = "std")]
1837impl From<net::Ipv4Addr> for Ipv4Addr {
1838    #[inline]
1839    fn from(ip: net::Ipv4Addr) -> Ipv4Addr {
1840        Ipv4Addr::new(ip.octets())
1841    }
1842}
1843
1844#[cfg(feature = "std")]
1845impl From<Ipv4Addr> for net::Ipv4Addr {
1846    #[inline]
1847    fn from(ip: Ipv4Addr) -> net::Ipv4Addr {
1848        net::Ipv4Addr::from(ip.0)
1849    }
1850}
1851
1852impl Display for Ipv4Addr {
1853    #[inline]
1854    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1855        write!(f, "{}.{}.{}.{}", self.0[0], self.0[1], self.0[2], self.0[3])
1856    }
1857}
1858
1859impl Debug for Ipv4Addr {
1860    #[inline]
1861    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1862        Display::fmt(self, f)
1863    }
1864}
1865
1866/// An IPv6 address.
1867///
1868/// # Layout
1869///
1870/// `Ipv6Addr` has the same layout as `[u8; 16]`, which is the layout that most
1871/// protocols use to represent an IPv6 address in their packet formats. This can
1872/// be useful when parsing an IPv6 address from a packet. For example:
1873///
1874/// ```rust
1875/// # use net_types::ip::Ipv6Addr;
1876/// /// The fixed part of an IPv6 packet header.
1877/// ///
1878/// /// `FixedHeader` has the same layout as the fixed part of an IPv6 packet
1879/// /// header.
1880/// #[repr(C)]
1881/// pub struct FixedHeader {
1882///     version_tc_flowlabel: [u8; 4],
1883///     payload_len: [u8; 2],
1884///     next_hdr: u8,
1885///     hop_limit: u8,
1886///     src_ip: Ipv6Addr,
1887///     dst_ip: Ipv6Addr,
1888/// }
1889/// ```
1890///
1891/// # `Display`
1892///
1893/// The [`Display`] impl for `Ipv6Addr` formats according to [RFC 5952].
1894///
1895/// Where RFC 5952 leaves decisions up to the implementation, `Ipv6Addr` matches
1896/// the behavior of [`std::net::Ipv6Addr`] - all IPv6 addresses are formatted
1897/// the same by `Ipv6Addr` as by `<std::net::Ipv6Addr as Display>::fmt`.
1898///
1899/// [RFC 5952]: https://datatracker.ietf.org/doc/html/rfc5952
1900#[derive(
1901    Copy,
1902    Clone,
1903    Default,
1904    PartialEq,
1905    Eq,
1906    PartialOrd,
1907    Ord,
1908    Hash,
1909    KnownLayout,
1910    FromBytes,
1911    IntoBytes,
1912    Immutable,
1913    Unaligned,
1914)]
1915#[repr(transparent)]
1916pub struct Ipv6Addr([u8; 16]);
1917
1918impl Ipv6Addr {
1919    /// Creates a new IPv6 address from 16-bit segments.
1920    #[inline]
1921    pub const fn new(segments: [u16; 8]) -> Ipv6Addr {
1922        #![allow(clippy::many_single_char_names)]
1923        let [a, b, c, d, e, f, g, h] = segments;
1924        let [aa, ab] = a.to_be_bytes();
1925        let [ba, bb] = b.to_be_bytes();
1926        let [ca, cb] = c.to_be_bytes();
1927        let [da, db] = d.to_be_bytes();
1928        let [ea, eb] = e.to_be_bytes();
1929        let [fa, fb] = f.to_be_bytes();
1930        let [ga, gb] = g.to_be_bytes();
1931        let [ha, hb] = h.to_be_bytes();
1932        Ipv6Addr([aa, ab, ba, bb, ca, cb, da, db, ea, eb, fa, fb, ga, gb, ha, hb])
1933    }
1934
1935    /// Creates a new IPv6 address from bytes.
1936    #[inline]
1937    pub const fn from_bytes(bytes: [u8; 16]) -> Ipv6Addr {
1938        Ipv6Addr(bytes)
1939    }
1940
1941    /// Gets the bytes of the IPv6 address.
1942    #[inline]
1943    pub const fn ipv6_bytes(&self) -> [u8; 16] {
1944        self.0
1945    }
1946
1947    /// Gets the 16-bit segments of the IPv6 address.
1948    #[inline]
1949    pub fn segments(&self) -> [u16; 8] {
1950        #![allow(clippy::many_single_char_names)]
1951        let [a, b, c, d, e, f, g, h]: [zerocopy::network_endian::U16; 8] =
1952            zerocopy::transmute!(self.ipv6_bytes());
1953        [a.into(), b.into(), c.into(), d.into(), e.into(), f.into(), g.into(), h.into()]
1954    }
1955
1956    /// Converts this `Ipv6Addr` to the IPv6 Solicited-Node Address, used in
1957    /// Neighbor Discovery, defined in [RFC 4291 Section 2.7.1].
1958    ///
1959    /// [RFC 4291 Section 2.7.1]: https://tools.ietf.org/html/rfc4291#section-2.7.1
1960    #[inline]
1961    pub const fn to_solicited_node_address(&self) -> MulticastAddr<Ipv6Addr> {
1962        // TODO(brunodalbo) benchmark this generation and evaluate if using
1963        //  bit operations with u128 could be faster. This is very likely
1964        //  going to be on a hot path.
1965
1966        // We know we are not breaking the guarantee that `MulticastAddr` provides
1967        // when calling `new_unchecked` because the address we provide it is
1968        // a multicast address as defined by RFC 4291 section 2.7.1.
1969        unsafe {
1970            MulticastAddr::new_unchecked(Ipv6Addr::from_bytes([
1971                0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xff, self.0[13], self.0[14],
1972                self.0[15],
1973            ]))
1974        }
1975    }
1976
1977    /// Is this a valid unicast address?
1978    ///
1979    /// A valid unicast address is any unicast address that can be bound to an
1980    /// interface (not the unspecified or loopback addresses).
1981    /// `addr.is_valid_unicast()` is equivalent to `!(addr.is_loopback() ||
1982    /// !addr.is_specified() || addr.is_multicast())`.
1983    #[inline]
1984    pub fn is_valid_unicast(&self) -> bool {
1985        !(self.is_loopback() || !self.is_specified() || self.is_multicast())
1986    }
1987
1988    /// Is this address in the (deprecated) site-local unicast subnet?
1989    ///
1990    /// `is_site_local` returns true if `self` is in the (deprecated)
1991    /// [`Ipv6::SITE_LOCAL_UNICAST_SUBNET`]. See that constant's documentation
1992    /// for more details on deprecation and how the subnet should be used in
1993    /// light of deprecation.
1994    #[inline]
1995    pub fn is_site_local(&self) -> bool {
1996        Ipv6::SITE_LOCAL_UNICAST_SUBNET.contains(self)
1997    }
1998
1999    /// Is this a unicast link-local address?
2000    ///
2001    /// `addr.is_unicast_link_local()` is equivalent to
2002    /// `addr.is_unicast_in_subnet(&Ipv6::LINK_LOCAL_UNICAST_SUBNET)`.
2003    #[inline]
2004    pub fn is_unicast_link_local(&self) -> bool {
2005        self.is_unicast_in_subnet(&Ipv6::LINK_LOCAL_UNICAST_SUBNET)
2006    }
2007
2008    /// Tries to extract the IPv4 address from an IPv4-compatible IPv6 address.
2009    ///
2010    /// IPv4-compatible IPv6 addresses were defined to assist in the IPv6
2011    /// transition, and are now specified in [RFC 4291 Section 2.5.5.1]. The
2012    /// lowest-order 32 bits carry an IPv4 address, while the highest-order 96
2013    /// bits are all set to 0 as in this diagram from the RFC:
2014    ///
2015    /// ```text
2016    /// |                80 bits               | 16 |      32 bits        |
2017    /// +--------------------------------------+--------------------------+
2018    /// |0000..............................0000|0000|    IPv4 address     |
2019    /// +--------------------------------------+----+---------------------+
2020    /// ```
2021    ///
2022    /// `to_ipv4_compatible` checks to see if `self` is an IPv4-compatible
2023    /// IPv6 address. If it is, the IPv4 address is extracted and returned.
2024    ///
2025    /// Per RFC 4291:
2026    ///
2027    /// > The 'IPv4-Compatible IPv6 address' is now deprecated because the
2028    /// > current IPv6 transition mechanisms no longer use these addresses. New
2029    /// > or updated implementations are not required to support this address
2030    /// > type.
2031    ///
2032    /// The more modern embedding format is IPv4-mapped IPv6 addressing - see
2033    /// [`to_ipv4_mapped`].
2034    ///
2035    /// [RFC 4291 Section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1
2036    /// [`to_ipv4_mapped`]: Ipv6Addr::to_ipv4_mapped
2037    pub fn to_ipv4_compatible(&self) -> Option<Ipv4Addr> {
2038        if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] = self.0 {
2039            Some(Ipv4Addr::new([a, b, c, d]))
2040        } else {
2041            None
2042        }
2043    }
2044
2045    /// Tries to extract the IPv4 address from an IPv4-mapped IPv6 address.
2046    ///
2047    /// IPv4-mapped IPv6 addresses are used to represent the addresses of IPv4
2048    /// nodes as IPv6 addresses, and are defined in [RFC 4291 Section 2.5.5.2].
2049    /// The lowest-order 32 bits carry an IPv4 address, the middle order 16 bits
2050    /// carry the literal 0xFFFF, and the highest order 80 bits are set to 0 as
2051    /// in this diagram from the RFC:
2052    ///
2053    /// ```text
2054    /// |                80 bits               | 16 |      32 bits        |
2055    /// +--------------------------------------+--------------------------+
2056    /// |0000..............................0000|FFFF|    IPv4 address     |
2057    /// +--------------------------------------+----+---------------------+
2058    /// ```
2059    ///
2060    /// `to_ipv4_mapped` checks to see if `self` is an IPv4-mapped
2061    /// IPv6 address. If it is, the IPv4 address is extracted and returned.
2062    ///
2063    /// [RFC 4291 Section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
2064    pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
2065        if let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] = self.0 {
2066            Some(Ipv4Addr::new([a, b, c, d]))
2067        } else {
2068            None
2069        }
2070    }
2071}
2072
2073impl sealed::Sealed for Ipv6Addr {}
2074
2075/// [`Ipv4Addr`] is convertible into [`Ipv6Addr`] through
2076/// [`Ipv4Addr::to_ipv6_mapped`].
2077impl From<Ipv4Addr> for Ipv6Addr {
2078    fn from(addr: Ipv4Addr) -> Ipv6Addr {
2079        *addr.to_ipv6_mapped()
2080    }
2081}
2082
2083impl IpAddress for Ipv6Addr {
2084    const BYTES: u8 = 16;
2085
2086    type Version = Ipv6;
2087
2088    #[inline]
2089    fn mask(&self, bits: u8) -> Ipv6Addr {
2090        assert!(bits <= 128);
2091        // Need to perform a checked shift left in case `bits == 128`, in which
2092        // case an unchecked shift left (`u128::MAX << bits`) would overflow,
2093        // causing a panic in debug mode.
2094        let mask = u128::MAX.checked_shl((128 - bits).into()).unwrap_or(0);
2095        Ipv6Addr((u128::from_be_bytes(self.0) & mask).to_be_bytes())
2096    }
2097
2098    #[inline]
2099    fn bytes(&self) -> &[u8] {
2100        &self.0
2101    }
2102
2103    #[inline]
2104    fn to_ip_addr(&self) -> IpAddr {
2105        IpAddr::V6(*self)
2106    }
2107
2108    #[inline]
2109    fn common_prefix_len(&self, other: &Ipv6Addr) -> u8 {
2110        let me = u128::from_be_bytes(self.0);
2111        let other = u128::from_be_bytes(other.0);
2112        // `same_bits` has a 0 wherever `me` and `other` have the same bit in a
2113        // given position, and a 1 wherever they have opposite bits.
2114        let same_bits = me ^ other;
2115        same_bits.leading_zeros() as u8
2116    }
2117
2118    #[inline]
2119    fn is_unicast_in_subnet(&self, subnet: &Subnet<Self>) -> bool {
2120        !self.is_multicast() && self.is_specified() && subnet.contains(self)
2121    }
2122
2123    fn subnet_into_either(subnet: Subnet<Ipv6Addr>) -> SubnetEither {
2124        SubnetEither::V6(subnet)
2125    }
2126
2127    #[inline]
2128    fn array_into_ip_addr<const N: usize>(
2129        addrs: [Self; N],
2130    ) -> IpAddr<[Ipv4Addr; N], [Ipv6Addr; N]> {
2131        IpAddr::V6(addrs)
2132    }
2133}
2134
2135impl UnicastAddress for Ipv6Addr {
2136    /// Is this a unicast address?
2137    ///
2138    /// `addr.is_unicast()` is equivalent to `!addr.is_multicast() &&
2139    /// addr.is_specified()`.
2140    #[inline]
2141    fn is_unicast(&self) -> bool {
2142        !self.is_multicast() && self.is_specified()
2143    }
2144}
2145
2146impl From<[u8; 16]> for Ipv6Addr {
2147    #[inline]
2148    fn from(bytes: [u8; 16]) -> Ipv6Addr {
2149        Ipv6Addr::from_bytes(bytes)
2150    }
2151}
2152
2153#[cfg(feature = "std")]
2154impl From<net::Ipv6Addr> for Ipv6Addr {
2155    #[inline]
2156    fn from(addr: net::Ipv6Addr) -> Ipv6Addr {
2157        Ipv6Addr::from_bytes(addr.octets())
2158    }
2159}
2160
2161#[cfg(feature = "std")]
2162impl From<Ipv6Addr> for net::Ipv6Addr {
2163    #[inline]
2164    fn from(addr: Ipv6Addr) -> net::Ipv6Addr {
2165        net::Ipv6Addr::from(addr.ipv6_bytes())
2166    }
2167}
2168
2169impl Display for Ipv6Addr {
2170    /// Formats an IPv6 address according to [RFC 5952].
2171    ///
2172    /// Where RFC 5952 leaves decisions up to the implementation, this function
2173    /// matches the behavior of [`std::net::Ipv6Addr`] - all IPv6 addresses are
2174    /// formatted the same by this function as by `<std::net::Ipv6Addr as
2175    /// Display>::fmt`.
2176    ///
2177    /// [RFC 5952]: https://datatracker.ietf.org/doc/html/rfc5952
2178    #[inline]
2179    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2180        // `fmt_inner` implements the core of the formatting algorithm, but does
2181        // not handle precision or width requirements. Those are handled below
2182        // by creating a scratch buffer, calling `fmt_inner` on that scratch
2183        // buffer, and then satisfying those requirements.
2184        fn fmt_inner<W: fmt::Write>(addr: &Ipv6Addr, w: &mut W) -> Result<(), fmt::Error> {
2185            // We special-case the unspecified address, localhost address, and
2186            // IPv4-mapped addresses, but not IPv4-compatible addresses. We
2187            // follow Rust's behavior here: https://github.com/rust-lang/rust/pull/112606
2188            if !addr.is_specified() {
2189                write!(w, "::")
2190            } else if addr.is_loopback() {
2191                write!(w, "::1")
2192            } else if let Some(v4) = addr.to_ipv4_mapped() {
2193                write!(w, "::ffff:{}", v4)
2194            } else {
2195                let segments = addr.segments();
2196
2197                let longest_zero_span = {
2198                    let mut longest_zero_span = 0..0;
2199                    let mut current_zero_span = 0..0;
2200                    for (i, seg) in segments.iter().enumerate() {
2201                        if *seg == 0 {
2202                            current_zero_span.end = i + 1;
2203                            if current_zero_span.len() > longest_zero_span.len() {
2204                                longest_zero_span = current_zero_span.clone();
2205                            }
2206                        } else {
2207                            let next_idx = i + 1;
2208                            current_zero_span = next_idx..next_idx;
2209                        }
2210                    }
2211                    longest_zero_span
2212                };
2213
2214                let write_slice = |w: &mut W, slice: &[u16]| {
2215                    if let [head, tail @ ..] = slice {
2216                        write!(w, "{:x}", head)?;
2217                        for seg in tail {
2218                            write!(w, ":{:x}", seg)?;
2219                        }
2220                    }
2221                    Ok(())
2222                };
2223
2224                // Note that RFC 5952 gives us a choice of when to compress a
2225                // run of zeroes:
2226                //
2227                //   It is possible to select whether or not to omit just one
2228                //   16-bit 0 field.
2229                //
2230                // Given this choice, we opt to match the stdlib's behavior.
2231                // This makes it easier to write tests (we can simply check to
2232                // see whether our behavior matches `std`'s behavior on a range
2233                // of inputs), and makes it so that our `Ipv6Addr` type is,
2234                // behaviorally, more of a drop-in for `std::net::Ipv6Addr` than
2235                // it would be if we were to diverge on formatting. This makes
2236                // replacing `std::net::Ipv6Addr` with our `Ipv6Addr` easier for
2237                // clients, and also makes it an easier choice since they don't
2238                // have to weigh whether the difference in behavior is
2239                // acceptable for them.
2240                if longest_zero_span.len() > 1 {
2241                    write_slice(w, &segments[..longest_zero_span.start])?;
2242                    w.write_str("::")?;
2243                    write_slice(w, &segments[longest_zero_span.end..])
2244                } else {
2245                    write_slice(w, &segments)
2246                }
2247            }
2248        }
2249
2250        if f.precision().is_none() && f.width().is_none() {
2251            // Fast path: No precision or width requirements, so write directly
2252            // to `f`.
2253            fmt_inner(self, f)
2254        } else {
2255            // Slow path: Precision or width requirement(s), so construct a
2256            // scratch buffer, use the `fmt_inner` to fill it, then use `f.pad`
2257            // to satisfy precision/width requirement(s).
2258
2259            // `[u8]` does not implement `core::fmt::Write`, so we provide our
2260            // own wrapper which does.
2261            struct ByteSlice<'a>(&'a mut [u8]);
2262
2263            impl<'a> fmt::Write for ByteSlice<'a> {
2264                fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
2265                    let from = s.as_bytes();
2266
2267                    if from.len() > self.0.len() {
2268                        return Err(fmt::Error);
2269                    }
2270
2271                    // Temporarily replace `self.0` with an empty slice and move
2272                    // the old value of `self.0` into our scope so that we can
2273                    // operate on it by value. This allows us to split it in two
2274                    // (`to` and `remaining`) and then overwrite `self.0` with
2275                    // `remaining`.
2276                    let to = mem::replace(&mut self.0, &mut [][..]);
2277                    let (to, remaining) = to.split_at_mut(from.len());
2278                    to.copy_from_slice(from);
2279
2280                    self.0 = remaining;
2281                    Ok(())
2282                }
2283            }
2284
2285            // The maximum length for an IPv6 address displays all 8 pairs of
2286            // bytes in hexadecimal representation (4 characters per two bytes
2287            // of IPv6 address), each separated with colons (7 colons total).
2288            const MAX_DISPLAY_LEN: usize = (4 * 8) + 7;
2289            let mut scratch = [0u8; MAX_DISPLAY_LEN];
2290            let mut scratch_slice = ByteSlice(&mut scratch[..]);
2291            // `fmt_inner` only returns an error if a method on `w` returns an
2292            // error. Since, in this call to `fmt_inner`, `w` is
2293            // `scratch_slice`, the only error that could happen would be if we
2294            // run out of space, but we know we won't because `scratch_slice`
2295            // has `MAX_DISPLAY_LEN` bytes, which is enough to hold any
2296            // formatted IPv6 address.
2297            fmt_inner(self, &mut scratch_slice)
2298                .expect("<Ipv6Addr as Display>::fmt: fmt_inner should have succeeded because the scratch buffer was long enough");
2299            let unwritten = scratch_slice.0.len();
2300            let len = MAX_DISPLAY_LEN - unwritten;
2301            // `fmt_inner` only writes valid UTF-8.
2302            let str = core::str::from_utf8(&scratch[..len])
2303                .expect("<Ipv6Addr as Display>::fmt: scratch buffer should contain valid UTF-8");
2304            f.pad(str)
2305        }
2306    }
2307}
2308
2309impl Debug for Ipv6Addr {
2310    #[inline]
2311    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2312        Display::fmt(self, f)
2313    }
2314}
2315
2316/// The source address from an IPv6 packet.
2317///
2318/// An `Ipv6SourceAddr` represents the source address from an IPv6 packet, which
2319/// may only be either:
2320///   * unicast and non-mapped (e.g. not an ipv4-mapped-ipv6 address), or
2321///   * unspecified.
2322#[allow(missing_docs)]
2323#[derive(Copy, Clone, Eq, PartialEq)]
2324pub enum Ipv6SourceAddr {
2325    Unicast(NonMappedAddr<UnicastAddr<Ipv6Addr>>),
2326    Unspecified,
2327}
2328
2329impl crate::sealed::Sealed for Ipv6SourceAddr {}
2330
2331impl Ipv6SourceAddr {
2332    /// Constructs a new `Ipv6SourceAddr`.
2333    ///
2334    /// Returns `None` if `addr` does not satisfy the properties required of an
2335    /// `Ipv6SourceAddr`.
2336    #[inline]
2337    pub fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2338        if let Some(addr) = UnicastAddr::new(addr) {
2339            NonMappedAddr::new(addr).map(Ipv6SourceAddr::Unicast)
2340        } else if !addr.is_specified() {
2341            Some(Ipv6SourceAddr::Unspecified)
2342        } else {
2343            None
2344        }
2345    }
2346}
2347
2348impl Witness<Ipv6Addr> for Ipv6SourceAddr {
2349    #[inline]
2350    fn new(addr: Ipv6Addr) -> Option<Ipv6SourceAddr> {
2351        Ipv6SourceAddr::new(addr)
2352    }
2353
2354    #[inline]
2355    unsafe fn new_unchecked(addr: Ipv6Addr) -> Ipv6SourceAddr {
2356        Ipv6SourceAddr::new(addr).unwrap()
2357    }
2358
2359    #[inline]
2360    fn into_addr(self) -> Ipv6Addr {
2361        match self {
2362            Ipv6SourceAddr::Unicast(addr) => **addr,
2363            Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2364        }
2365    }
2366}
2367
2368impl SpecifiedAddress for Ipv6SourceAddr {
2369    fn is_specified(&self) -> bool {
2370        self != &Ipv6SourceAddr::Unspecified
2371    }
2372}
2373
2374impl UnicastAddress for Ipv6SourceAddr {
2375    fn is_unicast(&self) -> bool {
2376        matches!(self, Ipv6SourceAddr::Unicast(_))
2377    }
2378}
2379
2380impl LinkLocalAddress for Ipv6SourceAddr {
2381    fn is_link_local(&self) -> bool {
2382        let addr: Ipv6Addr = self.into();
2383        addr.is_link_local()
2384    }
2385}
2386
2387impl MappedAddress for Ipv6SourceAddr {
2388    fn is_non_mapped(&self) -> bool {
2389        let addr: Ipv6Addr = self.into();
2390        addr.is_non_mapped()
2391    }
2392}
2393
2394impl From<Ipv6SourceAddr> for Ipv6Addr {
2395    fn from(addr: Ipv6SourceAddr) -> Ipv6Addr {
2396        addr.get()
2397    }
2398}
2399
2400impl From<&'_ Ipv6SourceAddr> for Ipv6Addr {
2401    fn from(addr: &Ipv6SourceAddr) -> Ipv6Addr {
2402        match addr {
2403            Ipv6SourceAddr::Unicast(addr) => addr.get(),
2404            Ipv6SourceAddr::Unspecified => Ipv6::UNSPECIFIED_ADDRESS,
2405        }
2406    }
2407}
2408
2409impl TryFrom<Ipv6Addr> for Ipv6SourceAddr {
2410    type Error = ();
2411    fn try_from(addr: Ipv6Addr) -> Result<Ipv6SourceAddr, ()> {
2412        Ipv6SourceAddr::new(addr).ok_or(())
2413    }
2414}
2415
2416impl AsRef<Ipv6Addr> for Ipv6SourceAddr {
2417    fn as_ref(&self) -> &Ipv6Addr {
2418        match self {
2419            Ipv6SourceAddr::Unicast(addr) => addr,
2420            Ipv6SourceAddr::Unspecified => &Ipv6::UNSPECIFIED_ADDRESS,
2421        }
2422    }
2423}
2424
2425impl Deref for Ipv6SourceAddr {
2426    type Target = Ipv6Addr;
2427
2428    fn deref(&self) -> &Ipv6Addr {
2429        self.as_ref()
2430    }
2431}
2432
2433impl Display for Ipv6SourceAddr {
2434    #[inline]
2435    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2436        match self {
2437            Ipv6SourceAddr::Unicast(addr) => write!(f, "{}", addr),
2438            Ipv6SourceAddr::Unspecified => write!(f, "::"),
2439        }
2440    }
2441}
2442
2443impl Debug for Ipv6SourceAddr {
2444    #[inline]
2445    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2446        Display::fmt(self, f)
2447    }
2448}
2449
2450/// An IPv6 address stored as a unicast or multicast witness type.
2451///
2452/// `UnicastOrMulticastIpv6Addr` is either a [`UnicastAddr`] or a
2453/// [`MulticastAddr`]. It allows the user to match on the unicast-ness or
2454/// multicast-ness of an IPv6 address and obtain a statically-typed witness in
2455/// each case. This is useful if the user needs to call different functions
2456/// which each take a witness type.
2457#[allow(missing_docs)]
2458#[derive(Copy, Clone, Eq, PartialEq)]
2459pub enum UnicastOrMulticastIpv6Addr {
2460    Unicast(UnicastAddr<Ipv6Addr>),
2461    Multicast(MulticastAddr<Ipv6Addr>),
2462}
2463
2464impl UnicastOrMulticastIpv6Addr {
2465    /// Constructs a new `UnicastOrMulticastIpv6Addr`.
2466    ///
2467    /// Returns `None` if `addr` is the unspecified address.
2468    pub fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2469        SpecifiedAddr::new(addr).map(UnicastOrMulticastIpv6Addr::from_specified)
2470    }
2471
2472    /// Constructs a new `UnicastOrMulticastIpv6Addr` from a specified address.
2473    pub fn from_specified(addr: SpecifiedAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2474        if addr.is_unicast() {
2475            UnicastOrMulticastIpv6Addr::Unicast(UnicastAddr(addr.get()))
2476        } else {
2477            UnicastOrMulticastIpv6Addr::Multicast(MulticastAddr(addr.get()))
2478        }
2479    }
2480}
2481
2482impl crate::sealed::Sealed for UnicastOrMulticastIpv6Addr {}
2483
2484impl Witness<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2485    #[inline]
2486    fn new(addr: Ipv6Addr) -> Option<UnicastOrMulticastIpv6Addr> {
2487        UnicastOrMulticastIpv6Addr::new(addr)
2488    }
2489
2490    #[inline]
2491    unsafe fn new_unchecked(addr: Ipv6Addr) -> UnicastOrMulticastIpv6Addr {
2492        UnicastOrMulticastIpv6Addr::new(addr).unwrap()
2493    }
2494
2495    #[inline]
2496    fn into_addr(self) -> Ipv6Addr {
2497        match self {
2498            UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.get(),
2499            UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.get(),
2500        }
2501    }
2502}
2503
2504impl UnicastAddress for UnicastOrMulticastIpv6Addr {
2505    fn is_unicast(&self) -> bool {
2506        matches!(self, UnicastOrMulticastIpv6Addr::Unicast(_))
2507    }
2508}
2509
2510impl MulticastAddress for UnicastOrMulticastIpv6Addr {
2511    fn is_multicast(&self) -> bool {
2512        matches!(self, UnicastOrMulticastIpv6Addr::Multicast(_))
2513    }
2514}
2515
2516impl LinkLocalAddress for UnicastOrMulticastIpv6Addr {
2517    fn is_link_local(&self) -> bool {
2518        match self {
2519            UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_link_local(),
2520            UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_link_local(),
2521        }
2522    }
2523}
2524
2525impl MappedAddress for UnicastOrMulticastIpv6Addr {
2526    fn is_non_mapped(&self) -> bool {
2527        match self {
2528            UnicastOrMulticastIpv6Addr::Unicast(addr) => addr.is_non_mapped(),
2529            UnicastOrMulticastIpv6Addr::Multicast(addr) => addr.is_non_mapped(),
2530        }
2531    }
2532}
2533
2534impl From<UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2535    fn from(addr: UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2536        addr.get()
2537    }
2538}
2539
2540impl From<&'_ UnicastOrMulticastIpv6Addr> for Ipv6Addr {
2541    fn from(addr: &UnicastOrMulticastIpv6Addr) -> Ipv6Addr {
2542        addr.get()
2543    }
2544}
2545
2546impl From<UnicastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2547    fn from(addr: UnicastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2548        UnicastOrMulticastIpv6Addr::Unicast(addr)
2549    }
2550}
2551
2552impl From<MulticastAddr<Ipv6Addr>> for UnicastOrMulticastIpv6Addr {
2553    fn from(addr: MulticastAddr<Ipv6Addr>) -> UnicastOrMulticastIpv6Addr {
2554        UnicastOrMulticastIpv6Addr::Multicast(addr)
2555    }
2556}
2557
2558impl TryFrom<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2559    type Error = ();
2560    fn try_from(addr: Ipv6Addr) -> Result<UnicastOrMulticastIpv6Addr, ()> {
2561        UnicastOrMulticastIpv6Addr::new(addr).ok_or(())
2562    }
2563}
2564
2565impl AsRef<Ipv6Addr> for UnicastOrMulticastIpv6Addr {
2566    fn as_ref(&self) -> &Ipv6Addr {
2567        match self {
2568            UnicastOrMulticastIpv6Addr::Unicast(addr) => addr,
2569            UnicastOrMulticastIpv6Addr::Multicast(addr) => addr,
2570        }
2571    }
2572}
2573
2574impl Deref for UnicastOrMulticastIpv6Addr {
2575    type Target = Ipv6Addr;
2576
2577    fn deref(&self) -> &Ipv6Addr {
2578        self.as_ref()
2579    }
2580}
2581
2582impl Display for UnicastOrMulticastIpv6Addr {
2583    #[inline]
2584    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2585        match self {
2586            UnicastOrMulticastIpv6Addr::Unicast(addr) => write!(f, "{}", addr),
2587            UnicastOrMulticastIpv6Addr::Multicast(addr) => write!(f, "{}", addr),
2588        }
2589    }
2590}
2591
2592impl Debug for UnicastOrMulticastIpv6Addr {
2593    #[inline]
2594    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2595        Display::fmt(self, f)
2596    }
2597}
2598
2599/// The error returned from [`Subnet::new`] and [`SubnetEither::new`].
2600#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2601pub enum SubnetError {
2602    /// The network prefix is longer than the number of bits in the address (32
2603    /// for IPv4/128 for IPv6).
2604    PrefixTooLong,
2605    /// The network address has some bits in the host part (past the network
2606    /// prefix) set to one.
2607    HostBitsSet,
2608}
2609
2610/// A prefix was provided which is longer than the number of bits in the address
2611/// (32 for IPv4/128 for IPv6).
2612#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2613pub struct PrefixTooLongError;
2614
2615/// An IP subnet.
2616///
2617/// `Subnet` is a combination of an IP network address and a prefix length.
2618#[derive(Copy, Clone, Eq, PartialEq, Hash)]
2619pub struct Subnet<A> {
2620    // invariant: only contains prefix bits
2621    network: A,
2622    prefix: u8,
2623}
2624
2625impl<A: core::cmp::Ord> core::cmp::PartialOrd for Subnet<A> {
2626    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
2627        Some(self.cmp(other))
2628    }
2629}
2630
2631/// Subnet ordering always orders from least-specific to most-specific subnet.
2632impl<A: core::cmp::Ord> core::cmp::Ord for Subnet<A> {
2633    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
2634        let Self { network, prefix } = self;
2635        let Self { network: other_network, prefix: other_prefix } = other;
2636        match prefix.cmp(other_prefix) {
2637            core::cmp::Ordering::Equal => network.cmp(other_network),
2638            ord => ord,
2639        }
2640    }
2641}
2642
2643impl<A> Subnet<A> {
2644    /// Creates a new subnet without enforcing correctness.
2645    ///
2646    /// # Safety
2647    ///
2648    /// Unlike `new`, `new_unchecked` does not validate that `prefix` is in the
2649    /// proper range, and does not check that `network` has only the top
2650    /// `prefix` bits set. It is up to the caller to guarantee that `prefix` is
2651    /// in the proper range, and that none of the bits of `network` beyond the
2652    /// prefix are set.
2653    #[inline]
2654    pub const unsafe fn new_unchecked(network: A, prefix: u8) -> Subnet<A> {
2655        Subnet { network, prefix }
2656    }
2657}
2658
2659impl<A: IpAddress> Subnet<A> {
2660    /// Creates a new subnet.
2661    ///
2662    /// `new` creates a new subnet with the given network address and prefix
2663    /// length. It returns `Err` if `prefix` is longer than the number of bits
2664    /// in this type of IP address (32 for IPv4 and 128 for IPv6) or if any of
2665    /// the host bits (beyond the first `prefix` bits) are set in `network`.
2666    #[inline]
2667    pub fn new(network: A, prefix: u8) -> Result<Subnet<A>, SubnetError> {
2668        if prefix > A::BYTES * 8 {
2669            return Err(SubnetError::PrefixTooLong);
2670        }
2671        // TODO(joshlf): Is there a more efficient way we can perform this
2672        // check?
2673        if network != network.mask(prefix) {
2674            return Err(SubnetError::HostBitsSet);
2675        }
2676        Ok(Subnet { network, prefix })
2677    }
2678
2679    /// Creates a new subnet from the address of a host in that subnet.
2680    ///
2681    /// Unlike [`new`], the `host` address may have host bits set.
2682    ///
2683    /// [`new`]: Subnet::new
2684    #[inline]
2685    pub fn from_host(host: A, prefix: u8) -> Result<Subnet<A>, PrefixTooLongError> {
2686        if prefix > A::BYTES * 8 {
2687            return Err(PrefixTooLongError);
2688        }
2689        let network = host.mask(prefix);
2690        Ok(Subnet { network, prefix })
2691    }
2692
2693    /// Gets the network address component of this subnet.
2694    ///
2695    /// Any bits beyond the prefix will be zero.
2696    #[inline]
2697    pub fn network(&self) -> A {
2698        self.network
2699    }
2700
2701    /// Gets the prefix length component of this subnet.
2702    #[inline]
2703    pub fn prefix(&self) -> u8 {
2704        self.prefix
2705    }
2706
2707    /// Tests whether an address is in this subnet.
2708    ///
2709    /// Tests whether `addr` is in this subnet by testing whether the prefix
2710    /// bits match the prefix bits of the subnet's network address. This is
2711    /// equivalent to `sub.network() == addr.mask(sub.prefix())`.
2712    #[inline]
2713    pub fn contains(&self, addr: &A) -> bool {
2714        self.network == addr.mask(self.prefix)
2715    }
2716}
2717
2718impl Subnet<Ipv4Addr> {
2719    // TODO(joshlf): If we introduce a separate type for an address in a subnet
2720    // (with fewer requirements than `AddrSubnet` has now so that a broadcast
2721    // address is representable), then that type could implement
2722    // `BroadcastAddress`, and `broadcast` could return
2723    // `BroadcastAddr<Foo<Ipv4Addr>>`.
2724
2725    /// Gets the broadcast address in this IPv4 subnet.
2726    #[inline]
2727    pub fn broadcast(self) -> Ipv4Addr {
2728        if self.prefix == 32 {
2729            // shifting right by the size of the value is undefined
2730            self.network
2731        } else {
2732            let mask = <u32>::max_value() >> self.prefix;
2733            Ipv4Addr::new((u32::from_be_bytes(self.network.0) | mask).to_be_bytes())
2734        }
2735    }
2736}
2737
2738impl<A: IpAddress> Display for Subnet<A> {
2739    #[inline]
2740    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2741        write!(f, "{}/{}", self.network, self.prefix)
2742    }
2743}
2744
2745impl<A: IpAddress> Debug for Subnet<A> {
2746    #[inline]
2747    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2748        write!(f, "{}/{}", self.network, self.prefix)
2749    }
2750}
2751
2752impl<A, I: Ip> GenericOverIp<I> for Subnet<A> {
2753    type Type = Subnet<I::Addr>;
2754}
2755
2756/// An IPv4 subnet or an IPv6 subnet.
2757///
2758/// `SubnetEither` is an enum of [`Subnet<Ipv4Addr>`] and `Subnet<Ipv6Addr>`.
2759///
2760/// [`Subnet<Ipv4Addr>`]: Subnet
2761#[allow(missing_docs)]
2762#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2763pub enum SubnetEither {
2764    V4(Subnet<Ipv4Addr>),
2765    V6(Subnet<Ipv6Addr>),
2766}
2767
2768impl SubnetEither {
2769    /// Creates a new subnet.
2770    ///
2771    /// `new` creates a new subnet with the given network address and prefix
2772    /// length. It returns `Err` if `prefix` is longer than the number of bits
2773    /// in this type of IP address (32 for IPv4 and 128 for IPv6) or if any of
2774    /// the host bits (beyond the first `prefix` bits) are set in `network`.
2775    #[inline]
2776    pub fn new(network: IpAddr, prefix: u8) -> Result<SubnetEither, SubnetError> {
2777        Ok(match network {
2778            IpAddr::V4(network) => SubnetEither::V4(Subnet::new(network, prefix)?),
2779            IpAddr::V6(network) => SubnetEither::V6(Subnet::new(network, prefix)?),
2780        })
2781    }
2782
2783    /// Creates a new subnet from the address of a host in that subnet.
2784    ///
2785    /// Unlike [`new`], the `host` address may have host bits set.
2786    ///
2787    /// [`new`]: SubnetEither::new
2788    #[inline]
2789    pub fn from_host(host: IpAddr, prefix: u8) -> Result<SubnetEither, PrefixTooLongError> {
2790        Ok(match host {
2791            IpAddr::V4(host) => SubnetEither::V4(Subnet::from_host(host, prefix)?),
2792            IpAddr::V6(host) => SubnetEither::V6(Subnet::from_host(host, prefix)?),
2793        })
2794    }
2795
2796    /// Gets the network and prefix.
2797    #[inline]
2798    pub fn net_prefix(&self) -> (IpAddr, u8) {
2799        match self {
2800            SubnetEither::V4(v4) => (v4.network.into(), v4.prefix),
2801            SubnetEither::V6(v6) => (v6.network.into(), v6.prefix),
2802        }
2803    }
2804}
2805
2806impl<A: IpAddress> From<Subnet<A>> for SubnetEither {
2807    fn from(subnet: Subnet<A>) -> SubnetEither {
2808        A::subnet_into_either(subnet)
2809    }
2810}
2811
2812/// The error returned from [`AddrSubnet::new`] and [`AddrSubnetEither::new`].
2813#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2814pub enum AddrSubnetError {
2815    /// The network prefix is longer than the number of bits in the address (32
2816    /// for IPv4/128 for IPv6).
2817    PrefixTooLong,
2818    /// The address is not a unicast address in the given subnet (see
2819    /// [`IpAddress::is_unicast_in_subnet`]).
2820    NotUnicastInSubnet,
2821    /// The address does not satisfy the requirements of the witness type.
2822    InvalidWitness,
2823}
2824
2825// TODO(joshlf): Is the unicast restriction always necessary, or will some users
2826// want the AddrSubnet functionality without that restriction?
2827
2828/// An address and that address's subnet.
2829///
2830/// An `AddrSubnet` is a pair of an address and a subnet which maintains the
2831/// invariant that the address is guaranteed to be a unicast address in the
2832/// subnet. `S` is the type of address ([`Ipv4Addr`] or [`Ipv6Addr`]), and `A`
2833/// is the type of the address in the subnet, which is always a witness wrapper
2834/// around `S`. By default, it is `SpecifiedAddr<S>`.
2835#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
2836pub struct AddrSubnet<S: IpAddress, A: Witness<S> + Copy = SpecifiedAddr<S>> {
2837    // TODO(joshlf): Would it be more performant to store these as just an
2838    // address and subnet mask? It would make the object smaller and so cheaper
2839    // to pass around, but it would make certain operations more expensive.
2840    addr: A,
2841    subnet: Subnet<S>,
2842}
2843
2844impl<S: IpAddress, A: Witness<S> + Copy> AddrSubnet<S, A> {
2845    /// Creates a new `AddrSubnet`.
2846    ///
2847    /// `new` is like [`from_witness`], except that it also converts `addr` into
2848    /// the appropriate witness type, returning
2849    /// [`AddrSubnetError::InvalidWitness`] if the conversion fails.
2850    ///
2851    /// [`from_witness`]: Witness::from_witness
2852    #[inline]
2853    pub fn new(addr: S, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2854        AddrSubnet::from_witness(A::new(addr).ok_or(AddrSubnetError::InvalidWitness)?, prefix)
2855    }
2856
2857    /// Creates a new `AddrSubnet` without checking for validity.
2858    ///
2859    /// # Safety
2860    ///
2861    /// Unlike [`new`], `new_unchecked` does not validate that `prefix` is in the
2862    /// proper range, and does not check that `addr` is a valid value for the
2863    /// witness type `A`. It is up to the caller to guarantee that `prefix` is
2864    /// in the proper range, and `A::new(addr)` is not `None`.
2865    ///
2866    /// [`new`]: AddrSubnet::new
2867    #[inline]
2868    pub unsafe fn new_unchecked(addr: S, prefix: u8) -> Self {
2869        let (subnet, addr) =
2870            unsafe { (Subnet::new_unchecked(addr.mask(prefix), prefix), A::new_unchecked(addr)) };
2871        AddrSubnet { addr, subnet }
2872    }
2873
2874    /// Creates a new `AddrSubnet` from an existing witness.
2875    ///
2876    /// `from_witness` creates a new `AddrSubnet` with the given address and
2877    /// prefix length. The network address of the subnet is taken to be the
2878    /// first `prefix` bits of the address. It returns `Err` if `prefix` is
2879    /// longer than the number of bits in this type of IP address (32 for IPv4
2880    /// and 128 for IPv6) or if `addr` is not a unicast address in the resulting
2881    /// subnet (see [`IpAddress::is_unicast_in_subnet`]).
2882    pub fn from_witness(addr: A, prefix: u8) -> Result<AddrSubnet<S, A>, AddrSubnetError> {
2883        if prefix > S::BYTES * 8 {
2884            return Err(AddrSubnetError::PrefixTooLong);
2885        }
2886        let subnet = Subnet { network: addr.as_ref().mask(prefix), prefix };
2887        if !addr.as_ref().is_unicast_in_subnet(&subnet) {
2888            return Err(AddrSubnetError::NotUnicastInSubnet);
2889        }
2890        Ok(AddrSubnet { addr, subnet })
2891    }
2892
2893    /// Gets the subnet.
2894    #[inline]
2895    pub fn subnet(&self) -> Subnet<S> {
2896        self.subnet
2897    }
2898
2899    /// Gets the address.
2900    #[inline]
2901    pub fn addr(&self) -> A {
2902        self.addr
2903    }
2904
2905    /// Gets the address and subnet.
2906    #[inline]
2907    pub fn addr_subnet(self) -> (A, Subnet<S>) {
2908        (self.addr, self.subnet)
2909    }
2910
2911    /// Constructs a new `AddrSubnet` of a different witness type.
2912    #[inline]
2913    pub fn to_witness<B: Witness<S> + Copy>(&self) -> AddrSubnet<S, B>
2914    where
2915        A: Into<B>,
2916    {
2917        AddrSubnet { addr: self.addr.into(), subnet: self.subnet }
2918    }
2919
2920    /// Wraps an additional witness onto this [`AddrSubnet`].
2921    #[inline]
2922    pub fn add_witness<B: Witness<A> + Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
2923        let addr = B::new(self.addr)?;
2924        Some(AddrSubnet { addr, subnet: self.subnet })
2925    }
2926
2927    /// Replaces the [`AddrSubnet`] witness.
2928    #[inline]
2929    pub fn replace_witness<B: Witness<S> + Copy>(&self) -> Option<AddrSubnet<S, B>> {
2930        let addr = B::new(self.addr.get())?;
2931        Some(AddrSubnet { addr, subnet: self.subnet })
2932    }
2933}
2934
2935impl<S: IpAddress, A: Witness<S> + Copy + Display> Display for AddrSubnet<S, A> {
2936    #[inline]
2937    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2938        write!(f, "{}/{}", self.addr, self.subnet.prefix)
2939    }
2940}
2941
2942impl<A: Witness<Ipv6Addr> + Copy> AddrSubnet<Ipv6Addr, A> {
2943    /// Gets the address as a [`UnicastAddr`] witness.
2944    ///
2945    /// Since one of the invariants on an `AddrSubnet` is that its contained
2946    /// address is unicast in its subnet, `ipv6_unicast_addr` can infallibly
2947    /// convert its stored address to a `UnicastAddr`.
2948    pub fn ipv6_unicast_addr(&self) -> UnicastAddr<Ipv6Addr> {
2949        unsafe { UnicastAddr::new_unchecked(self.addr.get()) }
2950    }
2951
2952    /// Constructs a new `AddrSubnet` which stores a [`UnicastAddr`] witness.
2953    ///
2954    /// Since one of the invariants on an `AddrSubnet` is that its contained
2955    /// address is unicast in its subnet, `to_unicast` can infallibly convert
2956    /// its stored address to a `UnicastAddr`.
2957    pub fn to_unicast(&self) -> AddrSubnet<Ipv6Addr, UnicastAddr<Ipv6Addr>> {
2958        let AddrSubnet { addr, subnet } = *self;
2959        let addr = unsafe { UnicastAddr::new_unchecked(addr.get()) };
2960        AddrSubnet { addr, subnet }
2961    }
2962}
2963
2964/// An IP prefix length.
2965#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, GenericOverIp)]
2966#[generic_over_ip(I, Ip)]
2967pub struct PrefixLength<I: Ip> {
2968    /// `inner` is guaranteed to be a valid prefix length for `I::Addr`.
2969    inner: u8,
2970    _ip: IpVersionMarker<I>,
2971}
2972
2973impl<I: Ip> PrefixLength<I> {
2974    /// Returns the prefix length.
2975    ///
2976    /// The returned length is guaranteed to be a valid prefix length for
2977    /// `I::Addr`.
2978    pub const fn get(self) -> u8 {
2979        let Self { inner, _ip } = self;
2980        inner
2981    }
2982
2983    /// Gets the subnet-mask representation of this prefix length.
2984    pub fn get_mask(self) -> I::Addr {
2985        I::map_ip(
2986            self,
2987            |prefix_len| Ipv4::LIMITED_BROADCAST_ADDRESS.mask(prefix_len.get()),
2988            |prefix_len| Ipv6Addr([u8::MAX; 16]).mask(prefix_len.get()),
2989        )
2990    }
2991
2992    /// Constructs a `PrefixLength` from a given prefix length without checking
2993    /// whether it is too long for the address type.
2994    ///
2995    /// # Safety
2996    /// `prefix_length` must be less than or equal to the number of bits in
2997    /// `I::Addr`. In other words, `prefix_length <= I::Addr::BYTES * 8`.
2998    pub const unsafe fn new_unchecked(prefix_length: u8) -> Self {
2999        Self { inner: prefix_length, _ip: I::VERSION_MARKER }
3000    }
3001
3002    /// Constructs a `PrefixLength` from a given unverified prefix length.
3003    ///
3004    /// Returns `Err(PrefixTooLongError)` if `prefix_length` is too long for the
3005    /// address type.
3006    pub const fn new(prefix_length: u8) -> Result<Self, PrefixTooLongError> {
3007        if prefix_length > I::Addr::BYTES * 8 {
3008            return Err(PrefixTooLongError);
3009        }
3010        Ok(Self { inner: prefix_length, _ip: I::VERSION_MARKER })
3011    }
3012
3013    /// Constructs a `PrefixLength` from an IP address representing a subnet mask.
3014    ///
3015    /// Returns `Err(NotSubnetMaskError)` if `subnet_mask` is not a valid subnet
3016    /// mask.
3017    pub fn try_from_subnet_mask(subnet_mask: I::Addr) -> Result<Self, NotSubnetMaskError> {
3018        let IpInvariant((count_ones, leading_ones)) = I::map_ip(
3019            subnet_mask,
3020            |subnet_mask| {
3021                let number = u32::from_be_bytes(subnet_mask.ipv4_bytes());
3022                IpInvariant((number.count_ones(), number.leading_ones()))
3023            },
3024            |subnet_mask| {
3025                let number = u128::from_be_bytes(subnet_mask.ipv6_bytes());
3026                IpInvariant((number.count_ones(), number.leading_ones()))
3027            },
3028        );
3029
3030        if leading_ones != count_ones {
3031            return Err(NotSubnetMaskError);
3032        }
3033
3034        Ok(Self {
3035            inner: u8::try_from(leading_ones)
3036                .expect("the number of bits in an IP address fits in u8"),
3037            _ip: IpVersionMarker::default(),
3038        })
3039    }
3040}
3041
3042impl<I: Ip> From<PrefixLength<I>> for u8 {
3043    fn from(value: PrefixLength<I>) -> Self {
3044        value.get()
3045    }
3046}
3047
3048/// An IP address was provided which is not a valid subnet mask (the address
3049/// has set bits after the first unset bit).
3050#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3051pub struct NotSubnetMaskError;
3052
3053/// A type which is witness to some property about an [`IpAddress`], `A`.
3054///
3055/// `IpAddressWitness<A>` extends [`Witness`] of the `IpAddress` type `A` by
3056/// adding an associated type for the type-erased `IpAddr` version of the same
3057/// witness type. For example, the following implementation is provided for
3058/// `SpecifiedAddr<A>`:
3059///
3060/// ```rust,ignore
3061/// impl<A: IpAddress> IpAddressWitness<A> for SpecifiedAddr<A> {
3062///     type IpAddrWitness = SpecifiedAddr<IpAddr>;
3063/// }
3064/// ```
3065pub trait IpAddressWitness<A: IpAddress>: Witness<A> {
3066    /// The type-erased version of `Self`.
3067    ///
3068    /// For example, `SpecifiedAddr<Ipv4Addr>: IpAddressWitness<IpAddrWitness =
3069    /// SpecifiedAddr<IpAddr>>`.
3070    type IpAddrWitness: IpAddrWitness + From<Self>;
3071}
3072
3073macro_rules! impl_ip_address_witness {
3074    ($witness:ident) => {
3075        impl<A: IpAddress> IpAddressWitness<A> for $witness<A> {
3076            type IpAddrWitness = $witness<IpAddr>;
3077        }
3078    };
3079}
3080
3081impl_ip_address_witness!(SpecifiedAddr);
3082impl_ip_address_witness!(MulticastAddr);
3083impl_ip_address_witness!(LinkLocalAddr);
3084
3085/// A type which is a witness to some property about an [`IpAddress`].
3086///
3087/// `IpAddrWitness` extends [`Witness`] of [`IpAddr`] by adding associated types
3088/// for the IPv4- and IPv6-specific versions of the same witness type. For
3089/// example, the following implementation is provided for
3090/// `SpecifiedAddr<IpAddr>`:
3091///
3092/// ```rust,ignore
3093/// impl IpAddrWitness for SpecifiedAddr<IpAddr> {
3094///     type V4 = SpecifiedAddr<Ipv4Addr>;
3095///     type V6 = SpecifiedAddr<Ipv6Addr>;
3096/// }
3097/// ```
3098pub trait IpAddrWitness: Witness<IpAddr> + Into<IpAddr<Self::V4, Self::V6>> + Copy {
3099    /// The IPv4-specific version of `Self`.
3100    ///
3101    /// For example, `SpecifiedAddr<IpAddr>: IpAddrWitness<V4 =
3102    /// SpecifiedAddr<Ipv4Addr>>`.
3103    type V4: Witness<Ipv4Addr> + Into<Self> + Copy;
3104
3105    /// The IPv6-specific version of `Self`.
3106    ///
3107    /// For example, `SpecifiedAddr<IpAddr>: IpAddrWitness<V6 =
3108    /// SpecifiedAddr<Ipv6Addr>>`.
3109    type V6: Witness<Ipv6Addr> + Into<Self> + Copy;
3110
3111    // TODO(https://github.com/rust-lang/rust/issues/44491): Remove these
3112    // functions once implied where bounds make them unnecessary.
3113
3114    /// Converts an IPv4-specific witness into a general witness.
3115    fn from_v4(addr: Self::V4) -> Self {
3116        addr.into()
3117    }
3118
3119    /// Converts an IPv6-specific witness into a general witness.
3120    fn from_v6(addr: Self::V6) -> Self {
3121        addr.into()
3122    }
3123}
3124
3125macro_rules! impl_ip_addr_witness {
3126    ($witness:ident) => {
3127        impl IpAddrWitness for $witness<IpAddr> {
3128            type V4 = $witness<Ipv4Addr>;
3129            type V6 = $witness<Ipv6Addr>;
3130        }
3131    };
3132}
3133
3134impl_ip_addr_witness!(SpecifiedAddr);
3135impl_ip_addr_witness!(MulticastAddr);
3136impl_ip_addr_witness!(LinkLocalAddr);
3137
3138/// An address and that address's subnet, either IPv4 or IPv6.
3139///
3140/// `AddrSubnetEither` is an enum of [`AddrSubnet<Ipv4Addr>`] and
3141/// `AddrSubnet<Ipv6Addr>`.
3142///
3143/// [`AddrSubnet<Ipv4Addr>`]: AddrSubnet
3144#[allow(missing_docs)]
3145#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
3146pub enum AddrSubnetEither<A: IpAddrWitness = SpecifiedAddr<IpAddr>> {
3147    V4(AddrSubnet<Ipv4Addr, A::V4>),
3148    V6(AddrSubnet<Ipv6Addr, A::V6>),
3149}
3150
3151impl<A: IpAddrWitness> AddrSubnetEither<A> {
3152    /// Creates a new `AddrSubnetEither`.
3153    ///
3154    /// `new` creates a new `AddrSubnetEither` with the given address and prefix
3155    /// length. It returns `Err` under the same conditions as
3156    /// [`AddrSubnet::new`].
3157    #[inline]
3158    pub fn new(addr: IpAddr, prefix: u8) -> Result<AddrSubnetEither<A>, AddrSubnetError> {
3159        Ok(match addr {
3160            IpAddr::V4(addr) => AddrSubnetEither::V4(AddrSubnet::new(addr, prefix)?),
3161            IpAddr::V6(addr) => AddrSubnetEither::V6(AddrSubnet::new(addr, prefix)?),
3162        })
3163    }
3164
3165    /// Creates a new `AddrSubnetEither` from trusted inputs.
3166    ///
3167    /// # Safety
3168    ///
3169    /// Unlike [`new`], this assumes that the provided address satisfies the
3170    /// requirements of the witness type `A`, and that `prefix` is not too large
3171    /// for the IP version of the address in `addr`.
3172    ///
3173    /// [`new`]: AddrSubnetEither::new
3174    #[inline]
3175    pub unsafe fn new_unchecked(addr: IpAddr, prefix: u8) -> Self {
3176        match addr {
3177            IpAddr::V4(addr) => {
3178                AddrSubnetEither::V4(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3179            }
3180            IpAddr::V6(addr) => {
3181                AddrSubnetEither::V6(unsafe { AddrSubnet::new_unchecked(addr, prefix) })
3182            }
3183        }
3184    }
3185
3186    /// Gets the IP address.
3187    pub fn addr(&self) -> A {
3188        match self {
3189            AddrSubnetEither::V4(v4) => v4.addr.into(),
3190            AddrSubnetEither::V6(v6) => v6.addr.into(),
3191        }
3192    }
3193
3194    /// Gets the IP address and prefix.
3195    #[inline]
3196    pub fn addr_prefix(&self) -> (A, u8) {
3197        match self {
3198            AddrSubnetEither::V4(v4) => (v4.addr.into(), v4.subnet.prefix),
3199            AddrSubnetEither::V6(v6) => (v6.addr.into(), v6.subnet.prefix),
3200        }
3201    }
3202
3203    /// Gets the IP address and subnet.
3204    #[inline]
3205    pub fn addr_subnet(&self) -> (A, SubnetEither) {
3206        match self {
3207            AddrSubnetEither::V4(v4) => (v4.addr.into(), SubnetEither::V4(v4.subnet)),
3208            AddrSubnetEither::V6(v6) => (v6.addr.into(), SubnetEither::V6(v6.subnet)),
3209        }
3210    }
3211}
3212
3213impl<S: IpAddress, A: IpAddressWitness<S> + Copy> From<AddrSubnet<S, A>>
3214    for AddrSubnetEither<A::IpAddrWitness>
3215{
3216    #[inline]
3217    fn from(addr_sub: AddrSubnet<S, A>) -> AddrSubnetEither<A::IpAddrWitness> {
3218        let (addr, sub) = addr_sub.addr_subnet();
3219        // This unwrap is safe because:
3220        // - `addr_sub: AddrSubnet<S, A>`, so we know that `addr` and
3221        //   `sub.prefix` are valid arguments to `AddrSubnet::new` (which is
3222        //   what `AddrSubnetEither::new` calls under the hood).
3223        // - `A::IpAddrWitness` is the same witness type as `A`, but wrapping
3224        //   `IpAddr` instead of `Ipv4Addr` or `Ipv6Addr`. `addr: A` means that
3225        //   `addr` satisfies the property witnessed by the witness type `A`,
3226        //   which is the same property witnessed by `A::IpAddrWitness`. Thus,
3227        //   we're guaranteed that, when `AddrSubnetEither::new` tries to
3228        //   construct the witness, it will succeed.
3229        AddrSubnetEither::new(addr.get().to_ip_addr(), sub.prefix()).unwrap()
3230    }
3231}
3232
3233impl<A> Display for AddrSubnetEither<A>
3234where
3235    A: IpAddrWitness,
3236    A::V4: Display,
3237    A::V6: Display,
3238{
3239    #[inline]
3240    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
3241        match self {
3242            Self::V4(a) => write!(f, "{}", a),
3243            Self::V6(a) => write!(f, "{}", a),
3244        }
3245    }
3246}
3247
3248/// Marks types that are generic over IP version.
3249///
3250/// This should be implemented by types that contain a generic parameter
3251/// [`I: Ip`](Ip) or [`A: IpAddress`](IpAddress) to allow them to be used with
3252/// [`Ip::map_ip`].
3253///
3254/// Implementations of this trait should generally be themselves generic over
3255/// `Ip`. For example:
3256/// ```
3257/// struct AddrAndSubnet<I: Ip> {
3258///   addr: I::Addr,
3259///   subnet: Subnet<I::Addr>
3260/// }
3261///
3262/// impl <I: Ip, NewIp: Ip> GenericOverIp<NewIp> for AddrAndSubnet<I> {
3263///   type Type = AddrAndSubnet<NewIp>;
3264/// }
3265/// ```
3266pub trait GenericOverIp<NewIp: Ip> {
3267    /// The type of `Self` when its IP-generic parameter is replaced with the
3268    /// type `NewIp`.
3269    type Type;
3270}
3271
3272/// Wrapper type that implements [`GenericOverIp`] with `Type<I: Ip>=Self`.
3273///
3274/// This can be used to make a compound type implement `GenericOverIp` with
3275/// some portion that is invariant over IP version.
3276pub struct IpInvariant<T>(pub T);
3277
3278impl<T> IpInvariant<T> {
3279    /// Consumes the `IpInvariant` and returns the wrapped value.
3280    pub fn into_inner(self) -> T {
3281        self.0
3282    }
3283}
3284
3285impl<I: Ip, T> GenericOverIp<I> for IpInvariant<T> {
3286    type Type = Self;
3287}
3288
3289impl<I: Ip> GenericOverIp<I> for core::convert::Infallible {
3290    type Type = Self;
3291}
3292
3293/// A wrapper structure to add an IP version marker to an IP-invariant type.
3294#[derive(GenericOverIp, Default, Debug, PartialOrd, Ord, Eq, PartialEq, Hash)]
3295#[generic_over_ip(I, Ip)]
3296pub struct IpMarked<I: Ip, T> {
3297    inner: T,
3298    _marker: IpVersionMarker<I>,
3299}
3300
3301impl<I: Ip, T> Deref for IpMarked<I, T> {
3302    type Target = T;
3303
3304    fn deref(&self) -> &Self::Target {
3305        self.as_ref()
3306    }
3307}
3308
3309impl<I: Ip, T> DerefMut for IpMarked<I, T> {
3310    fn deref_mut(&mut self) -> &mut Self::Target {
3311        self.as_mut()
3312    }
3313}
3314impl<I: Ip, T> AsRef<T> for IpMarked<I, T> {
3315    fn as_ref(&self) -> &T {
3316        &self.inner
3317    }
3318}
3319
3320impl<I: Ip, T> AsMut<T> for IpMarked<I, T> {
3321    fn as_mut(&mut self) -> &mut T {
3322        &mut self.inner
3323    }
3324}
3325
3326impl<I: Ip, T> IpMarked<I, T> {
3327    /// Constructs a new `IpMarked` from the provided `T`.
3328    pub fn new(inner: T) -> Self {
3329        Self { inner, _marker: IpVersionMarker::<I>::new() }
3330    }
3331
3332    /// Consumes the `IpMarked` and returns the contained `T` by value.
3333    pub fn into_inner(self) -> T {
3334        let Self { inner, _marker } = self;
3335        inner
3336    }
3337
3338    /// Gets an immutable reference to the underlying `T`.
3339    pub fn get(&self) -> &T {
3340        self.as_ref()
3341    }
3342
3343    /// Gets an mutable reference to the underlying `T`.
3344    pub fn get_mut(&mut self) -> &mut T {
3345        self.as_mut()
3346    }
3347}
3348
3349/// Calls the provided macro with all suffixes of the input.
3350macro_rules! for_each_tuple_ {
3351        ( $m:ident !! ) => ( $m! { });
3352        ( $m:ident !! $h:ident, $($t:ident,)* ) => (
3353            $m! { $h $($t)* }
3354            for_each_tuple_! { $m !! $($t,)* }
3355        );
3356    }
3357
3358/// Calls the provided macro with 0-12 type parameters.
3359macro_rules! for_each_tuple {
3360    ($m:ident) => {
3361        for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, }
3362    };
3363}
3364
3365/// Implements GenericOverIp for a tuple with the provided generic parameters.
3366macro_rules! ip_generic_tuple {
3367        () => {
3368            impl<I: Ip> GenericOverIp<I> for () {
3369                type Type = Self;
3370            }
3371        };
3372        ( $name0:ident $($name:ident)* ) => (
3373            impl<P: Ip, $name0: GenericOverIp<P>, $($name: GenericOverIp<P>,)*>
3374            GenericOverIp<P> for ($name0, $($name,)*) {
3375                type Type = ($name0::Type, $($name::Type,)*);
3376            }
3377        );
3378    }
3379
3380for_each_tuple!(ip_generic_tuple);
3381
3382macro_rules! ip_generic {
3383    ( $type:ident < $($params:ident),* >) => {
3384        impl<IpType: Ip, $($params: GenericOverIp<IpType>),*>
3385        GenericOverIp<IpType> for $type<$($params),*> {
3386            type Type = $type<$($params::Type),*>;
3387        }
3388    };
3389    ( $type:ident) => {
3390        impl<IpType: Ip> GenericOverIp<IpType> for $type {
3391            type Type = Self;
3392        }
3393    }
3394}
3395
3396// Implement GenericOverIp for common types.
3397ip_generic!(bool);
3398ip_generic!(isize);
3399ip_generic!(i8);
3400ip_generic!(i16);
3401ip_generic!(i32);
3402ip_generic!(i64);
3403ip_generic!(usize);
3404ip_generic!(u8);
3405ip_generic!(u16);
3406ip_generic!(u32);
3407ip_generic!(u64);
3408ip_generic!(Option<T>);
3409ip_generic!(Result<R, E>);
3410#[cfg(feature = "std")]
3411ip_generic!(Vec<T>);
3412
3413impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s T
3414where
3415    T::Type: 's,
3416{
3417    type Type = &'s T::Type;
3418}
3419
3420impl<'s, NewIp: Ip, T: GenericOverIp<NewIp>> GenericOverIp<NewIp> for &'s mut T
3421where
3422    T::Type: 's,
3423{
3424    type Type = &'s mut T::Type;
3425}
3426
3427#[cfg(test)]
3428mod tests {
3429    use super::*;
3430    use test_case::test_case;
3431
3432    #[test]
3433    fn test_map_ip_associated_constant() {
3434        fn get_loopback_address<I: Ip>() -> SpecifiedAddr<I::Addr> {
3435            I::map_ip((), |()| Ipv4::LOOPBACK_ADDRESS, |()| Ipv6::LOOPBACK_ADDRESS)
3436        }
3437
3438        assert_eq!(get_loopback_address::<Ipv4>(), Ipv4::LOOPBACK_ADDRESS);
3439        assert_eq!(get_loopback_address::<Ipv6>(), Ipv6::LOOPBACK_ADDRESS);
3440    }
3441
3442    #[test]
3443    fn test_map_ip_different_behavior() {
3444        fn filter_v4<I: Ip>(addr: I::Addr) -> Option<I::Addr> {
3445            I::map_ip(addr, |addr| Some(addr), |_addr| None)
3446        }
3447
3448        assert_eq!(filter_v4::<Ipv4>(*Ipv4::LOOPBACK_ADDRESS), Some(*Ipv4::LOOPBACK_ADDRESS));
3449        assert_eq!(filter_v4::<Ipv6>(*Ipv6::LOOPBACK_ADDRESS), None);
3450    }
3451
3452    #[test]
3453    fn test_map_ip_extension_trait_fn() {
3454        trait FakeIpExt: Ip {
3455            fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr;
3456        }
3457
3458        impl FakeIpExt for Ipv4 {
3459            fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3460                let Ipv4Addr(mut bytes) = a;
3461                bytes.reverse();
3462                Ipv4Addr(bytes)
3463            }
3464        }
3465        impl FakeIpExt for Ipv6 {
3466            fn reverse_addr_bytes(a: Self::Addr) -> Self::Addr {
3467                let Ipv6Addr(mut bytes) = a;
3468                bytes.reverse();
3469                Ipv6Addr(bytes)
3470            }
3471        }
3472
3473        fn reverse_bytes<A: IpAddress>(addr: A) -> A
3474        where
3475            A::Version: FakeIpExt,
3476        {
3477            A::Version::map_ip(addr, Ipv4::reverse_addr_bytes, Ipv6::reverse_addr_bytes)
3478        }
3479
3480        assert_eq!(reverse_bytes(Ipv4Addr([1, 2, 3, 4])), Ipv4Addr([4, 3, 2, 1]));
3481        assert_eq!(
3482            reverse_bytes(Ipv6Addr([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])),
3483            Ipv6Addr([16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
3484        );
3485    }
3486
3487    #[test]
3488    fn test_map_ip_extension_trait_associated_type() {
3489        trait FakeIpExt: Ip {
3490            type PackedInt;
3491        }
3492        impl FakeIpExt for Ipv4 {
3493            type PackedInt = u32;
3494        }
3495        impl FakeIpExt for Ipv6 {
3496            type PackedInt = u128;
3497        }
3498
3499        #[derive(Debug, PartialEq)]
3500        struct Int<T>(T);
3501
3502        impl<T, I: FakeIpExt> GenericOverIp<I> for Int<T> {
3503            type Type = Int<I::PackedInt>;
3504        }
3505
3506        fn from_be_bytes<A: IpAddress>(addr: A) -> Int<<A::Version as FakeIpExt>::PackedInt>
3507        where
3508            A::Version: FakeIpExt,
3509        {
3510            A::Version::map_ip(
3511                addr,
3512                |Ipv4Addr(bytes)| Int(<Ipv4 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3513                |Ipv6Addr(bytes)| Int(<Ipv6 as FakeIpExt>::PackedInt::from_be_bytes(bytes)),
3514            )
3515        }
3516
3517        assert_eq!(from_be_bytes(Ipv4::LOOPBACK_ADDRESS.get()), Int(0x7f000001u32));
3518        assert_eq!(from_be_bytes(Ipv6::LOOPBACK_ADDRESS.get()), Int(1u128));
3519    }
3520
3521    #[test]
3522    fn map_ip_twice() {
3523        struct FooV4 {
3524            field: Ipv4Addr,
3525        }
3526
3527        impl Default for FooV4 {
3528            fn default() -> Self {
3529                Self { field: Ipv4::UNSPECIFIED_ADDRESS }
3530            }
3531        }
3532
3533        struct FooV6 {
3534            field: Ipv6Addr,
3535        }
3536
3537        impl Default for FooV6 {
3538            fn default() -> Self {
3539                Self { field: Ipv6::UNSPECIFIED_ADDRESS }
3540            }
3541        }
3542
3543        trait IpExt {
3544            type Foo: Default;
3545        }
3546
3547        impl IpExt for Ipv4 {
3548            type Foo = FooV4;
3549        }
3550
3551        impl IpExt for Ipv6 {
3552            type Foo = FooV6;
3553        }
3554
3555        #[derive(GenericOverIp)]
3556        #[generic_over_ip(I, Ip)]
3557        struct Foo<I: IpExt>(I::Foo);
3558
3559        fn do_something<I: Ip + IpExt>(
3560            foo: Foo<I>,
3561            extra_foo: Foo<I>,
3562            captured_foo: Foo<I>,
3563        ) -> I::Addr {
3564            let addr: I::Addr = map_ip_twice!(I, foo, |Foo(foo)| { foo.field });
3565
3566            // Observe that we can use an associated item with `map_ip_twice!
3567            // too.
3568            let _: I::Addr =
3569                map_ip_twice!(<<I as Ip>::Addr as IpAddress>::Version, extra_foo, |Foo(foo)| {
3570                    // Since `captured_foo` is captured rather than fed through the
3571                    // generic-over-ip input, this wouldn't work if `I` was aliased
3572                    // concretely to `Ipv4` or `Ipv6`.
3573                    let _: &Foo<I> = &captured_foo;
3574                    foo.field
3575                });
3576
3577            addr
3578        }
3579
3580        assert_eq!(
3581            do_something(
3582                Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3583                Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS }),
3584                Foo::<Ipv4>(FooV4 { field: Ipv4::UNSPECIFIED_ADDRESS })
3585            ),
3586            Ipv4::UNSPECIFIED_ADDRESS
3587        );
3588        assert_eq!(
3589            do_something(
3590                Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3591                Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS }),
3592                Foo::<Ipv6>(FooV6 { field: Ipv6::UNSPECIFIED_ADDRESS })
3593            ),
3594            Ipv6::UNSPECIFIED_ADDRESS
3595        );
3596
3597        fn do_something_with_default_type_alias_shadowing<I: Ip>() -> (I::Addr, IpVersion) {
3598            let (field, IpInvariant(version)) = map_ip_twice!(I, (), |()| {
3599                // Note that there's no `IpExt` bound on `I`, so `I` wouldn't
3600                // work here unless it was automatically aliased to `Ipv4` or `Ipv6`.
3601                let foo: Foo<I> = Foo(<I as IpExt>::Foo::default());
3602                (foo.0.field, IpInvariant(I::VERSION))
3603            },);
3604            (field, version)
3605        }
3606
3607        fn do_something_with_type_alias<I: Ip>() -> (I::Addr, IpVersion) {
3608            // Show that the type alias inside the macro shadows
3609            // whatever it was bound to outside the macro.
3610            #[allow(dead_code)]
3611            type IpAlias = usize;
3612
3613            let (field, IpInvariant(version)) = map_ip_twice!(I as IpAlias, (), |()| {
3614                // Note that there's no `IpExt` bound on `I`, so `I` wouldn't
3615                // work here -- only `IpAlias`, since `IpAlias` is explicitly
3616                // an alias of `Ipv4` or `Ipv6`.
3617                let foo: Foo<IpAlias> = Foo(<IpAlias as IpExt>::Foo::default());
3618                (foo.0.field, IpInvariant(IpAlias::VERSION))
3619            },);
3620            (field, version)
3621        }
3622
3623        assert_eq!(
3624            do_something_with_default_type_alias_shadowing::<Ipv4>(),
3625            (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3626        );
3627        assert_eq!(
3628            do_something_with_default_type_alias_shadowing::<Ipv6>(),
3629            (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3630        );
3631        assert_eq!(
3632            do_something_with_type_alias::<Ipv4>(),
3633            (Ipv4::UNSPECIFIED_ADDRESS, IpVersion::V4)
3634        );
3635        assert_eq!(
3636            do_something_with_type_alias::<Ipv6>(),
3637            (Ipv6::UNSPECIFIED_ADDRESS, IpVersion::V6)
3638        );
3639    }
3640
3641    #[test]
3642    fn test_loopback_unicast() {
3643        // The loopback addresses are constructed as `SpecifiedAddr`s directly,
3644        // bypassing the actual check against `is_specified`. Test that that's
3645        // actually valid.
3646        assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
3647        assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
3648    }
3649
3650    #[test]
3651    fn test_specified() {
3652        // For types that implement SpecifiedAddress,
3653        // UnicastAddress::is_unicast, MulticastAddress::is_multicast, and
3654        // LinkLocalAddress::is_link_local all imply
3655        // SpecifiedAddress::is_specified. Test that that's true for both IPv4
3656        // and IPv6.
3657
3658        assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_specified());
3659        assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_specified());
3660
3661        // Unicast
3662
3663        assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_unicast());
3664
3665        let unicast = Ipv6Addr([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
3666        assert!(unicast.is_unicast());
3667        assert!(unicast.is_specified());
3668
3669        // Multicast
3670
3671        assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_multicast());
3672        assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_multicast());
3673
3674        let multicast = Ipv4::MULTICAST_SUBNET.network;
3675        assert!(multicast.is_multicast());
3676        assert!(multicast.is_specified());
3677        let multicast = Ipv6::MULTICAST_SUBNET.network;
3678        assert!(multicast.is_multicast());
3679        assert!(multicast.is_specified());
3680
3681        // Link-local
3682
3683        assert!(!Ipv4::UNSPECIFIED_ADDRESS.is_link_local());
3684        assert!(!Ipv6::UNSPECIFIED_ADDRESS.is_link_local());
3685
3686        let link_local = Ipv4::LINK_LOCAL_UNICAST_SUBNET.network;
3687        assert!(link_local.is_link_local());
3688        assert!(link_local.is_specified());
3689        let link_local = Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network;
3690        assert!(link_local.is_link_local());
3691        assert!(link_local.is_specified());
3692        let link_local = Ipv6::LINK_LOCAL_UNICAST_SUBNET.network;
3693        assert!(link_local.is_link_local());
3694        assert!(link_local.is_specified());
3695        let mut link_local = Ipv6::MULTICAST_SUBNET.network;
3696        link_local.0[1] = 0x02;
3697        assert!(link_local.is_link_local());
3698        assert!(link_local.is_specified());
3699        assert!(Ipv6::LOOPBACK_ADDRESS.is_link_local());
3700    }
3701
3702    #[test]
3703    fn test_link_local() {
3704        // IPv4
3705        assert!(Ipv4::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3706        assert!(Ipv4::LINK_LOCAL_MULTICAST_SUBNET.network.is_link_local());
3707
3708        // IPv6
3709        assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_link_local());
3710        assert!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.is_unicast_link_local());
3711        let mut addr = Ipv6::MULTICAST_SUBNET.network;
3712        for flags in 0..=0x0F {
3713            // Set the scope to link-local and the flags to `flags`.
3714            addr.0[1] = (flags << 4) | 0x02;
3715            // Test that a link-local multicast address is always considered
3716            // link-local regardless of which flags are set.
3717            assert!(addr.is_link_local());
3718            assert!(!addr.is_unicast_link_local());
3719        }
3720
3721        // Test that a non-multicast address (outside of the link-local subnet)
3722        // is never considered link-local even if the bits are set that, in a
3723        // multicast address, would put it in the link-local scope.
3724        let mut addr = Ipv6::LOOPBACK_ADDRESS.get();
3725        // Explicitly set the scope to link-local.
3726        addr.0[1] = 0x02;
3727        assert!(!addr.is_link_local());
3728    }
3729
3730    #[test]
3731    fn test_subnet_new() {
3732        assert_eq!(
3733            Subnet::new(Ipv4Addr::new([255, 255, 255, 255]), 32).unwrap(),
3734            Subnet { network: Ipv4Addr::new([255, 255, 255, 255]), prefix: 32 },
3735        );
3736        // Prefix exceeds 32 bits
3737        assert_eq!(
3738            Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 33),
3739            Err(SubnetError::PrefixTooLong)
3740        );
3741        assert_eq!(
3742            Subnet::from_host(Ipv4Addr::new([255, 255, 255, 255]), 33),
3743            Err(PrefixTooLongError)
3744        );
3745        // Network address has more than top 8 bits set
3746        assert_eq!(Subnet::new(Ipv4Addr::new([255, 255, 0, 0]), 8), Err(SubnetError::HostBitsSet));
3747        // Host address is allowed to have host bits set
3748        assert_eq!(
3749            Subnet::from_host(Ipv4Addr::new([255, 255, 0, 0]), 8),
3750            Ok(Subnet { network: Ipv4Addr::new([255, 0, 0, 0]), prefix: 8 })
3751        );
3752
3753        assert_eq!(
3754            AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32).unwrap(),
3755            AddrSubnet {
3756                addr: SpecifiedAddr(Ipv4Addr::new([1, 2, 3, 4])),
3757                subnet: Subnet { network: Ipv4Addr::new([1, 2, 3, 4]), prefix: 32 }
3758            }
3759        );
3760        // The unspecified address will always fail because it is not valid for
3761        // the `SpecifiedAddr` witness (use assert, not assert_eq, because
3762        // AddrSubnet doesn't impl Debug).
3763        assert!(
3764            AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::UNSPECIFIED_ADDRESS, 16)
3765                == Err(AddrSubnetError::InvalidWitness)
3766        );
3767        assert!(
3768            AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv6::UNSPECIFIED_ADDRESS, 64)
3769                == Err(AddrSubnetError::InvalidWitness)
3770        );
3771        // Prefix exceeds 32/128 bits
3772        assert!(
3773            AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([1, 2, 3, 4]), 33)
3774                == Err(AddrSubnetError::PrefixTooLong)
3775        );
3776        assert!(
3777            AddrSubnet::<_, SpecifiedAddr<_>>::new(
3778                Ipv6Addr::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
3779                129,
3780            ) == Err(AddrSubnetError::PrefixTooLong)
3781        );
3782        // Limited broadcast
3783        assert!(
3784            AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4::LIMITED_BROADCAST_ADDRESS.get(), 16)
3785                == Err(AddrSubnetError::NotUnicastInSubnet)
3786        );
3787        // Subnet broadcast
3788        assert!(
3789            AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([192, 168, 255, 255]), 16)
3790                == Err(AddrSubnetError::NotUnicastInSubnet)
3791        );
3792        // Multicast
3793        assert!(
3794            AddrSubnet::<_, SpecifiedAddr<_>>::new(Ipv4Addr::new([224, 0, 0, 1]), 16)
3795                == Err(AddrSubnetError::NotUnicastInSubnet)
3796        );
3797        assert!(
3798            AddrSubnet::<_, SpecifiedAddr<_>>::new(
3799                Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
3800                64,
3801            ) == Err(AddrSubnetError::NotUnicastInSubnet)
3802        );
3803
3804        // If we use the `LinkLocalAddr` witness type, then non link-local
3805        // addresses are rejected. Note that this address was accepted above
3806        // when `SpecifiedAddr` was used.
3807        assert!(
3808            AddrSubnet::<_, LinkLocalAddr<Ipv4Addr>>::new(Ipv4Addr::new([1, 2, 3, 4]), 32)
3809                == Err(AddrSubnetError::InvalidWitness)
3810        );
3811    }
3812
3813    #[test]
3814    fn test_is_unicast_in_subnet() {
3815        // Valid unicast in subnet
3816        let subnet =
3817            Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).expect("1.2.0.0/16 is a valid subnet");
3818        assert!(Ipv4Addr::new([1, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3819        assert!(!Ipv4Addr::new([2, 2, 3, 4]).is_unicast_in_subnet(&subnet));
3820
3821        let subnet =
3822            Subnet::new(Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 64)
3823                .expect("1::/64 is a valid subnet");
3824        assert!(Ipv6Addr::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3825            .is_unicast_in_subnet(&subnet));
3826        assert!(!Ipv6Addr::from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3827            .is_unicast_in_subnet(&subnet));
3828
3829        // Unspecified address
3830        assert!(!Ipv4::UNSPECIFIED_ADDRESS
3831            .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 16).unwrap()));
3832        assert!(!Ipv6::UNSPECIFIED_ADDRESS
3833            .is_unicast_in_subnet(&Subnet::new(Ipv6::UNSPECIFIED_ADDRESS, 64).unwrap()));
3834        // The "31- or 32-bit prefix" exception doesn't apply to the unspecified
3835        // address (IPv4 only).
3836        assert!(!Ipv4::UNSPECIFIED_ADDRESS
3837            .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 31).unwrap()));
3838        assert!(!Ipv4::UNSPECIFIED_ADDRESS
3839            .is_unicast_in_subnet(&Subnet::new(Ipv4::UNSPECIFIED_ADDRESS, 32).unwrap()));
3840        // All-zeroes host part (IPv4 only)
3841        assert!(!Ipv4Addr::new([1, 2, 0, 0])
3842            .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap()));
3843        // Exception: 31- or 32-bit prefix (IPv4 only)
3844        assert!(Ipv4Addr::new([1, 2, 3, 0])
3845            .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 31).unwrap()));
3846        assert!(Ipv4Addr::new([1, 2, 3, 0])
3847            .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 3, 0]), 32).unwrap()));
3848        // Limited broadcast (IPv4 only)
3849        assert!(!Ipv4::LIMITED_BROADCAST_ADDRESS
3850            .get()
3851            .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([128, 0, 0, 0]), 1).unwrap()));
3852        // Subnet broadcast (IPv4 only)
3853        assert!(!Ipv4Addr::new([1, 2, 255, 255])
3854            .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 0, 0]), 16).unwrap()));
3855        // Exception: 31- or 32-bit prefix (IPv4 only)
3856        assert!(Ipv4Addr::new([1, 2, 255, 255])
3857            .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 254]), 31).unwrap()));
3858        assert!(Ipv4Addr::new([1, 2, 255, 255])
3859            .is_unicast_in_subnet(&Subnet::new(Ipv4Addr::new([1, 2, 255, 255]), 32).unwrap()));
3860        // Multicast
3861        assert!(!Ipv4Addr::new([224, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::MULTICAST_SUBNET));
3862        assert!(!Ipv6Addr::from([0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
3863            .is_unicast_in_subnet(&Ipv6::MULTICAST_SUBNET));
3864        // Class E (IPv4 only)
3865        assert!(!Ipv4Addr::new([240, 0, 0, 1]).is_unicast_in_subnet(&Ipv4::CLASS_E_SUBNET));
3866    }
3867
3868    macro_rules! add_mask_test {
3869            ($name:ident, $addr:ident, $from_ip:expr => {
3870                $($mask:expr => $to_ip:expr),*
3871            }) => {
3872                #[test]
3873                fn $name() {
3874                    let from = $addr::from($from_ip);
3875                    $(assert_eq!(from.mask($mask), $addr::from($to_ip), "(`{}`.mask({}))", from, $mask);)*
3876                }
3877            };
3878            ($name:ident, $addr:ident, $from_ip:expr => {
3879                $($mask:expr => $to_ip:expr),*,
3880            }) => {
3881                add_mask_test!($name, $addr, $from_ip => { $($mask => $to_ip),* });
3882            };
3883        }
3884
3885    add_mask_test!(v4_full_mask, Ipv4Addr, [255, 254, 253, 252] => {
3886        32 => [255, 254, 253, 252],
3887        28 => [255, 254, 253, 240],
3888        24 => [255, 254, 253, 0],
3889        20 => [255, 254, 240, 0],
3890        16 => [255, 254, 0,   0],
3891        12 => [255, 240, 0,   0],
3892        8  => [255, 0,   0,   0],
3893        4  => [240, 0,   0,   0],
3894        0  => [0,   0,   0,   0],
3895    });
3896
3897    add_mask_test!(v6_full_mask, Ipv6Addr,
3898        [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0] => {
3899            128 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0],
3900            112 => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0x00, 0x00],
3901            96  => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0x00, 0x00, 0x00, 0x00],
3902            80  => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3903            64  => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3904            48  => [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3905            32  => [0xFF, 0xFE, 0xFD, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3906            16  => [0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3907            8   => [0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3908            0   => [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
3909        }
3910    );
3911
3912    #[test_case([255, 255, 255, 0] => Ok(24))]
3913    #[test_case([255, 255, 254, 0] => Ok(23))]
3914    #[test_case([255, 255, 253, 0] => Err(NotSubnetMaskError))]
3915    #[test_case([255, 255, 0, 255] => Err(NotSubnetMaskError))]
3916    #[test_case([255, 255, 255, 255] => Ok(32))]
3917    #[test_case([0, 0, 0, 0] => Ok(0))]
3918    #[test_case([0, 0, 0, 255] => Err(NotSubnetMaskError))]
3919    fn test_ipv4_prefix_len_try_from_subnet_mask(
3920        subnet_mask: [u8; 4],
3921    ) -> Result<u8, NotSubnetMaskError> {
3922        let subnet_mask = Ipv4Addr::from(subnet_mask);
3923        PrefixLength::<Ipv4>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
3924    }
3925
3926    #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(64))]
3927    #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(63))]
3928    #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
3929    #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0, 0, 0, 0, 0, 0, 0, 1] => Err(NotSubnetMaskError))]
3930    #[test_case([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(0))]
3931    #[test_case([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] => Ok(128))]
3932    #[test_case([0, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] => Err(NotSubnetMaskError))]
3933    fn test_ipv6_prefix_len_try_from_subnet_mask(
3934        subnet_mask: [u8; 16],
3935    ) -> Result<u8, NotSubnetMaskError> {
3936        let subnet_mask = Ipv6Addr::from(subnet_mask);
3937        PrefixLength::<Ipv6>::try_from_subnet_mask(subnet_mask).map(|prefix_len| prefix_len.get())
3938    }
3939
3940    #[test_case(0 => true)]
3941    #[test_case(1 => true)]
3942    #[test_case(32 => true)]
3943    #[test_case(33 => false)]
3944    #[test_case(128 => false)]
3945    #[test_case(129 => false)]
3946    #[test_case(255 => false)]
3947    fn test_ipv4_prefix_len_new(prefix_len: u8) -> bool {
3948        PrefixLength::<Ipv4>::new(prefix_len).is_ok()
3949    }
3950
3951    #[test_case(0 => true)]
3952    #[test_case(1 => true)]
3953    #[test_case(32 => true)]
3954    #[test_case(33 => true)]
3955    #[test_case(128 => true)]
3956    #[test_case(129 => false)]
3957    #[test_case(255 => false)]
3958    fn test_ipv6_prefix_len_new(prefix_len: u8) -> bool {
3959        PrefixLength::<Ipv6>::new(prefix_len).is_ok()
3960    }
3961
3962    #[test_case(0 => [0, 0, 0, 0])]
3963    #[test_case(6 => [252, 0, 0, 0])]
3964    #[test_case(16 => [255, 255, 0, 0])]
3965    #[test_case(25 => [255, 255, 255, 128])]
3966    #[test_case(32 => [255, 255, 255, 255])]
3967    fn test_ipv4_prefix_len_get_mask(prefix_len: u8) -> [u8; 4] {
3968        let Ipv4Addr(inner) = PrefixLength::<Ipv4>::new(prefix_len).unwrap().get_mask();
3969        inner
3970    }
3971
3972    #[test_case(0 => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
3973    #[test_case(6 => [0xFC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])]
3974    #[test_case(64 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])]
3975    #[test_case(65 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0])]
3976    #[test_case(128 => [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])]
3977    fn test_ipv6_prefix_len_get_mask(prefix_len: u8) -> [u8; 16] {
3978        let Ipv6Addr(inner) = PrefixLength::<Ipv6>::new(prefix_len).unwrap().get_mask();
3979        inner
3980    }
3981
3982    #[test]
3983    fn test_ipv6_solicited_node() {
3984        let addr = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
3985        let solicited = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
3986        assert_eq!(addr.to_solicited_node_address().get(), solicited);
3987    }
3988
3989    #[test]
3990    fn test_ipv6_address_types() {
3991        assert!(!Ipv6Addr::from([0; 16]).is_specified());
3992        assert!(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1]).is_loopback());
3993        let link_local = Ipv6Addr::new([0xfe80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
3994        assert!(link_local.is_link_local());
3995        assert!(link_local.is_valid_unicast());
3996        assert!(link_local.to_solicited_node_address().is_multicast());
3997        let global_unicast = Ipv6Addr::new([0x80, 0, 0, 0, 0x52e5, 0x49ff, 0xfeb5, 0x5aa0]);
3998        assert!(global_unicast.is_valid_unicast());
3999        assert!(global_unicast.to_solicited_node_address().is_multicast());
4000
4001        let multi = Ipv6Addr::new([0xff02, 0, 0, 0, 0, 0x01, 0xffb5, 0x5aa0]);
4002        assert!(multi.is_multicast());
4003        assert!(!multi.is_valid_unicast());
4004    }
4005
4006    #[test]
4007    fn test_const_witness() {
4008        // Test that all of the addresses that we initialize at compile time
4009        // using `new_unchecked` constructors are valid for their witness types.
4010        assert!(Ipv4::LOOPBACK_ADDRESS.0.is_specified());
4011        assert!(Ipv6::LOOPBACK_ADDRESS.0.is_specified());
4012        assert!(Ipv4::LIMITED_BROADCAST_ADDRESS.0.is_specified());
4013        assert!(Ipv4::ALL_ROUTERS_MULTICAST_ADDRESS.0.is_multicast());
4014        assert!(Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4015        assert!(Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS.0.is_multicast());
4016    }
4017
4018    #[test]
4019    fn test_ipv6_scope() {
4020        use Ipv6ReservedScope::*;
4021        use Ipv6Scope::*;
4022        use Ipv6UnassignedScope::*;
4023
4024        // Test unicast scopes.
4025        assert_eq!(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network.scope(), SiteLocal);
4026        assert_eq!(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network.scope(), LinkLocal);
4027        assert_eq!(Ipv6::UNSPECIFIED_ADDRESS.scope(), Global);
4028
4029        // Test multicast scopes.
4030        let assert_scope = |value, scope| {
4031            let mut addr = Ipv6::MULTICAST_SUBNET.network;
4032            // Set the "scop" field manually.
4033            addr.0[1] |= value;
4034            assert_eq!(addr.scope(), scope);
4035        };
4036        assert_scope(0, Reserved(Scope0));
4037        assert_scope(1, InterfaceLocal);
4038        assert_scope(2, LinkLocal);
4039        assert_scope(3, Reserved(Scope3));
4040        assert_scope(4, AdminLocal);
4041        assert_scope(5, SiteLocal);
4042        assert_scope(6, Unassigned(Scope6));
4043        assert_scope(7, Unassigned(Scope7));
4044        assert_scope(8, OrganizationLocal);
4045        assert_scope(9, Unassigned(Scope9));
4046        assert_scope(0xA, Unassigned(ScopeA));
4047        assert_scope(0xB, Unassigned(ScopeB));
4048        assert_scope(0xC, Unassigned(ScopeC));
4049        assert_scope(0xD, Unassigned(ScopeD));
4050        assert_scope(0xE, Global);
4051        assert_scope(0xF, Reserved(ScopeF));
4052    }
4053
4054    #[test]
4055    fn test_ipv6_multicast_scope_id() {
4056        const ALL_SCOPES: &[Ipv6Scope] = &[
4057            Ipv6Scope::Reserved(Ipv6ReservedScope::Scope0),
4058            Ipv6Scope::InterfaceLocal,
4059            Ipv6Scope::LinkLocal,
4060            Ipv6Scope::Reserved(Ipv6ReservedScope::Scope3),
4061            Ipv6Scope::AdminLocal,
4062            Ipv6Scope::SiteLocal,
4063            Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope6),
4064            Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope7),
4065            Ipv6Scope::OrganizationLocal,
4066            Ipv6Scope::Unassigned(Ipv6UnassignedScope::Scope9),
4067            Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeA),
4068            Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeB),
4069            Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeC),
4070            Ipv6Scope::Unassigned(Ipv6UnassignedScope::ScopeD),
4071            Ipv6Scope::Global,
4072            Ipv6Scope::Reserved(Ipv6ReservedScope::ScopeF),
4073        ];
4074        for (i, a) in ALL_SCOPES.iter().enumerate() {
4075            assert_eq!(a.multicast_scope_id(), i.try_into().unwrap());
4076        }
4077    }
4078
4079    #[test]
4080    fn test_ipv4_embedded() {
4081        // Test Ipv4Addr's to_ipv6_compatible and to_ipv6_mapped methods.
4082
4083        assert_eq!(
4084            Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_compatible(),
4085            Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4])
4086        );
4087        assert_eq!(
4088            Ipv4Addr::new([1, 2, 3, 4]).to_ipv6_mapped().get(),
4089            Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]),
4090        );
4091
4092        // Test Ipv6Addr's to_ipv4_compatible and to_ipv4_mapped methods.
4093
4094        let compatible = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4]);
4095        let mapped = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 1, 2, 3, 4]);
4096        let not_embedded = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 1, 2, 3, 4]);
4097        let v4 = Ipv4Addr::new([1, 2, 3, 4]);
4098
4099        assert_eq!(compatible.to_ipv4_compatible(), Some(v4));
4100        assert_eq!(compatible.to_ipv4_mapped(), None);
4101
4102        assert_eq!(mapped.to_ipv4_compatible(), None);
4103        assert_eq!(mapped.to_ipv4_mapped(), Some(v4));
4104
4105        assert_eq!(not_embedded.to_ipv4_compatible(), None);
4106        assert_eq!(not_embedded.to_ipv4_mapped(), None);
4107
4108        assert_eq!(
4109            NonMappedAddr::new(compatible),
4110            Some(unsafe { NonMappedAddr::new_unchecked(compatible) })
4111        );
4112        assert_eq!(NonMappedAddr::new(mapped), None);
4113        assert_eq!(
4114            NonMappedAddr::new(not_embedded),
4115            Some(unsafe { NonMappedAddr::new_unchecked(not_embedded) })
4116        );
4117        assert_eq!(NonMappedAddr::new(v4), Some(unsafe { NonMappedAddr::new_unchecked(v4) }));
4118    }
4119
4120    #[test]
4121    fn test_common_prefix_len_ipv6() {
4122        let ip1 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4123        let ip2 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4124        let ip3 = Ipv6Addr::from([0xFF, 0xFF, 0x80, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4125        let ip4 = Ipv6Addr::from([0xFF, 0xFF, 0xC0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4126        let compare_with_ip1 = |target, expect| {
4127            assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4128        };
4129        compare_with_ip1(ip1, 128);
4130        compare_with_ip1(ip2, 0);
4131        compare_with_ip1(ip3, 24);
4132        compare_with_ip1(ip4, 17);
4133    }
4134
4135    #[test]
4136    fn test_common_prefix_len_ipv4() {
4137        let ip1 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0]);
4138        let ip2 = Ipv4Addr::new([0, 0, 0, 0]);
4139        let ip3 = Ipv4Addr::new([0xFF, 0xFF, 0x80, 0xFF]);
4140        let ip4 = Ipv4Addr::new([0xFF, 0xFF, 0xC0, 0x20]);
4141        let compare_with_ip1 = |target, expect| {
4142            assert_eq!(ip1.common_prefix_len(&target), expect, "{} <=> {}", ip1, target);
4143        };
4144        compare_with_ip1(ip1, 32);
4145        compare_with_ip1(ip2, 0);
4146        compare_with_ip1(ip3, 24);
4147        compare_with_ip1(ip4, 17);
4148    }
4149
4150    #[test]
4151    fn test_ipv6_display() {
4152        // Test that `addr` is formatted the same by our `Display` impl as by
4153        // the standard library's `Display` impl. Optionally test that it
4154        // matches a particular expected string.
4155        fn test_one(addr: Ipv6Addr, expect: Option<&str>) {
4156            let formatted = format!("{}", addr);
4157            if let Some(expect) = expect {
4158                assert_eq!(formatted, expect);
4159            }
4160
4161            // NOTE: We use `std` here even though we're not inside of the
4162            // `std_tests` module because we're using `std` to test
4163            // functionality that is present even when the `std` Cargo feature
4164            // is not used.
4165            //
4166            // Note that we use `std::net::Ipv6Addr::from(addr.segments())`
4167            // rather than `std::net::Ipv6Addr::from(addr)` because, when the
4168            // `std` Cargo feature is disabled, the `From<Ipv6Addr> for
4169            // std::net::Ipv6Addr` impl is not emitted.
4170            let formatted_std = format!("{}", std::net::Ipv6Addr::from(addr.segments()));
4171            assert_eq!(formatted, formatted_std);
4172        }
4173
4174        test_one(Ipv6::UNSPECIFIED_ADDRESS, Some("::"));
4175        test_one(*Ipv6::LOOPBACK_ADDRESS, Some("::1"));
4176        test_one(Ipv6::MULTICAST_SUBNET.network, Some("ff00::"));
4177        test_one(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network, Some("fe80::"));
4178        test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4179        test_one(*Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::1"));
4180        test_one(*Ipv6::ALL_ROUTERS_LINK_LOCAL_MULTICAST_ADDRESS, Some("ff02::2"));
4181        test_one(Ipv6::SITE_LOCAL_UNICAST_SUBNET.network, Some("fec0::"));
4182        test_one(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), Some("1::"));
4183        test_one(Ipv6Addr::new([0, 0, 0, 1, 2, 3, 4, 5]), Some("::1:2:3:4:5"));
4184
4185        // Treating each pair of bytes as a bit (either 0x0000 or 0x0001), cycle
4186        // through every possible IPv6 address. Since the formatting algorithm
4187        // is only sensitive to zero vs nonzero for any given byte pair, this
4188        // gives us effectively complete coverage of the input space.
4189        for byte in 0u8..=255 {
4190            test_one(
4191                Ipv6Addr::new([
4192                    u16::from(byte & 0b1),
4193                    u16::from((byte & 0b10) >> 1),
4194                    u16::from((byte & 0b100) >> 2),
4195                    u16::from((byte & 0b1000) >> 3),
4196                    u16::from((byte & 0b10000) >> 4),
4197                    u16::from((byte & 0b100000) >> 5),
4198                    u16::from((byte & 0b1000000) >> 6),
4199                    u16::from((byte & 0b10000000) >> 7),
4200                ]),
4201                None,
4202            );
4203        }
4204    }
4205
4206    #[test_case(Ipv4::UNSPECIFIED_ADDRESS, Ipv4AddressClass::A; "first_class_a")]
4207    #[test_case(Ipv4Addr::new([127, 255, 255, 255]), Ipv4AddressClass::A; "last_class_a")]
4208    #[test_case(Ipv4Addr::new([128, 0, 0, 0]), Ipv4AddressClass::B; "first_class_b")]
4209    #[test_case(Ipv4Addr::new([191, 255, 255, 255]), Ipv4AddressClass::B; "last_class_b")]
4210    #[test_case(Ipv4Addr::new([192, 0, 0, 0]), Ipv4AddressClass::C; "first_class_c")]
4211    #[test_case(Ipv4Addr::new([223, 255, 255, 255]), Ipv4AddressClass::C; "last_class_c")]
4212    #[test_case(Ipv4Addr::new([224, 0, 0, 0]), Ipv4AddressClass::D; "first_class_d")]
4213    #[test_case(Ipv4Addr::new([239, 255, 255, 255]), Ipv4AddressClass::D; "last_class_d")]
4214    #[test_case(Ipv4Addr::new([240, 0, 0, 0]), Ipv4AddressClass::E; "first_class_e")]
4215    #[test_case(Ipv4Addr::new([255, 255, 255, 255]), Ipv4AddressClass::E; "last_class_e")]
4216    fn ipv4addr_class(addr: Ipv4Addr, class: Ipv4AddressClass) {
4217        assert_eq!(addr.class(), class)
4218    }
4219
4220    #[test_case(
4221        Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 24).unwrap(),
4222        Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap()
4223    ; "ipv4_same_prefix")]
4224    #[test_case(
4225        Subnet::new(Ipv4Addr::new([192, 168, 2, 0]), 24).unwrap(),
4226        Subnet::new(Ipv4Addr::new([192, 168, 1, 0]), 32).unwrap()
4227    ; "ipv4_by_prefix")]
4228    #[test_case(
4229        Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4230        Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap()
4231    ; "ipv6_same_prefix")]
4232    #[test_case(
4233        Subnet::new(Ipv6Addr::new([2, 0, 0, 0, 0, 0, 0, 0]), 64).unwrap(),
4234        Subnet::new(Ipv6Addr::new([1, 0, 0, 0, 0, 0, 0, 0]), 128).unwrap()
4235    ; "ipv6_by_prefix")]
4236    fn subnet_ord<A: core::cmp::Ord>(a: Subnet<A>, b: Subnet<A>) {
4237        assert!(a < b);
4238    }
4239
4240    #[cfg(feature = "std")]
4241    mod std_tests {
4242        use super::*;
4243
4244        #[test]
4245        fn test_conversions() {
4246            let v4 = Ipv4Addr::new([127, 0, 0, 1]);
4247            let v6 = Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
4248            let std_v4 = net::Ipv4Addr::new(127, 0, 0, 1);
4249            let std_v6 = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
4250
4251            let converted: IpAddr = net::IpAddr::V4(std_v4).into();
4252            assert_eq!(converted, IpAddr::V4(v4));
4253            let converted: IpAddr = net::IpAddr::V6(std_v6).into();
4254            assert_eq!(converted, IpAddr::V6(v6));
4255
4256            let converted: net::IpAddr = IpAddr::V4(v4).into();
4257            assert_eq!(converted, net::IpAddr::V4(std_v4));
4258            let converted: net::IpAddr = IpAddr::V6(v6).into();
4259            assert_eq!(converted, net::IpAddr::V6(std_v6));
4260
4261            let converted: Ipv4Addr = std_v4.into();
4262            assert_eq!(converted, v4);
4263            let converted: Ipv6Addr = std_v6.into();
4264            assert_eq!(converted, v6);
4265
4266            let converted: net::Ipv4Addr = v4.into();
4267            assert_eq!(converted, std_v4);
4268            let converted: net::Ipv6Addr = v6.into();
4269            assert_eq!(converted, std_v6);
4270        }
4271    }
4272}
4273
4274/// Tests of the [`GenericOverIp`] derive macro.
4275#[cfg(test)]
4276mod macro_test {
4277    use super::*;
4278
4279    /// No-op function that will only compile if `T::Type<I> = Other`.
4280    fn assert_ip_generic_is<T, I, Other>()
4281    where
4282        I: Ip,
4283        T: GenericOverIp<I, Type = Other>,
4284    {
4285        // Do nothing; this function just serves to assert that the argument
4286        // does in fact implement GenericOverIp.
4287    }
4288
4289    macro_rules! assert_ip_generic {
4290        ($name:ident, Ip $(,$($param:ident),*)?) => {
4291            assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4292            assert_ip_generic_is::<$name<Ipv4 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4293            assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv4, $name<Ipv4 $(, $($param,)*)?>>();
4294            assert_ip_generic_is::<$name<Ipv6 $(, $($param,)*)?>, Ipv6, $name<Ipv6 $(, $($param,)*)?>>();
4295        };
4296        ($name:ident, IpAddress $(,$($param:ident),*)?) => {
4297            assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4298            assert_ip_generic_is::<$name<Ipv4Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4299            assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv4, $name<Ipv4Addr $(, $($param,)*)?>>();
4300            assert_ip_generic_is::<$name<Ipv6Addr $(, $($param,)*)?>, Ipv6, $name<Ipv6Addr $(, $($param,)*)?>>();
4301        };
4302        ($name:ident $(,$($param:ident),*)?) => {
4303            assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4304            assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4305            assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv4, $name<$($($param,)*)?>>();
4306            assert_ip_generic_is::<$name<$($($param,)*)?>, Ipv6, $name<$($($param,)*)?>>();
4307        };
4308    }
4309
4310    #[test]
4311    fn struct_with_ip_version_parameter() {
4312        #[allow(dead_code)]
4313        #[derive(GenericOverIp)]
4314        #[generic_over_ip(I, Ip)]
4315        struct Generic<I: Ip> {
4316            addr: I::Addr,
4317        }
4318
4319        assert_ip_generic!(Generic, Ip);
4320    }
4321
4322    #[test]
4323    fn struct_with_unbounded_ip_version_parameter() {
4324        #[allow(dead_code)]
4325        #[derive(GenericOverIp)]
4326        #[generic_over_ip(I, Ip)]
4327        struct Generic<I> {
4328            addr: core::marker::PhantomData<I>,
4329        }
4330
4331        assert_ip_generic!(Generic, Ip);
4332    }
4333
4334    #[test]
4335    fn struct_with_ip_address_parameter() {
4336        #[allow(dead_code)]
4337        #[derive(GenericOverIp)]
4338        #[generic_over_ip(A, IpAddress)]
4339        struct Generic<A: IpAddress> {
4340            addr: A,
4341        }
4342
4343        assert_ip_generic!(Generic, IpAddress);
4344    }
4345
4346    #[test]
4347    fn struct_with_unbounded_ip_address_parameter() {
4348        #[allow(dead_code)]
4349        #[derive(GenericOverIp)]
4350        #[generic_over_ip(A, IpAddress)]
4351        struct Generic<A> {
4352            addr: A,
4353        }
4354
4355        assert_ip_generic!(Generic, IpAddress);
4356    }
4357
4358    #[test]
4359    fn struct_with_generic_over_ip_parameter() {
4360        #[derive(GenericOverIp)]
4361        #[generic_over_ip(I, Ip)]
4362        struct InnerGeneric<I: Ip> {
4363            addr: I::Addr,
4364        }
4365
4366        #[derive(GenericOverIp)]
4367        #[generic_over_ip(T, GenericOverIp)]
4368        struct Generic<T> {
4369            foo: T,
4370        }
4371
4372        fn do_something<I: Ip>(g: Generic<InnerGeneric<I>>) {
4373            I::map_ip(
4374                g,
4375                |g| {
4376                    let _: Ipv4Addr = g.foo.addr;
4377                },
4378                |g| {
4379                    let _: Ipv6Addr = g.foo.addr;
4380                },
4381            )
4382        }
4383
4384        do_something::<Ipv4>(Generic { foo: InnerGeneric { addr: Ipv4::UNSPECIFIED_ADDRESS } });
4385
4386        do_something::<Ipv6>(Generic { foo: InnerGeneric { addr: Ipv6::UNSPECIFIED_ADDRESS } });
4387    }
4388
4389    #[test]
4390    fn enum_with_ip_version_parameter() {
4391        #[allow(dead_code)]
4392        #[derive(GenericOverIp)]
4393        #[generic_over_ip(I, Ip)]
4394        enum Generic<I: Ip> {
4395            A(I::Addr),
4396            B(I::Addr),
4397        }
4398
4399        assert_ip_generic!(Generic, Ip);
4400    }
4401
4402    #[test]
4403    fn enum_with_unbounded_ip_version_parameter() {
4404        #[allow(dead_code)]
4405        #[derive(GenericOverIp)]
4406        #[generic_over_ip(I, Ip)]
4407        enum Generic<I> {
4408            A(core::marker::PhantomData<I>),
4409            B(core::marker::PhantomData<I>),
4410        }
4411
4412        assert_ip_generic!(Generic, Ip);
4413    }
4414
4415    #[test]
4416    fn enum_with_ip_address_parameter() {
4417        #[allow(dead_code)]
4418        #[derive(GenericOverIp)]
4419        #[generic_over_ip(A, IpAddress)]
4420        enum Generic<A: IpAddress> {
4421            A(A),
4422            B(A),
4423        }
4424
4425        assert_ip_generic!(Generic, IpAddress);
4426    }
4427
4428    #[test]
4429    fn enum_with_unbounded_ip_address_parameter() {
4430        #[allow(dead_code)]
4431        #[derive(GenericOverIp)]
4432        #[generic_over_ip(A, IpAddress)]
4433        enum Generic<A> {
4434            A(A),
4435            B(A),
4436        }
4437
4438        assert_ip_generic!(Generic, IpAddress);
4439    }
4440
4441    #[test]
4442    fn struct_with_ip_version_and_other_parameters() {
4443        #[allow(dead_code)]
4444        #[derive(GenericOverIp)]
4445        #[generic_over_ip(I, Ip)]
4446        struct AddrAndDevice<I: Ip, D> {
4447            addr: I::Addr,
4448            device: D,
4449        }
4450        struct Device;
4451
4452        assert_ip_generic!(AddrAndDevice, Ip, Device);
4453    }
4454
4455    #[test]
4456    fn enum_with_ip_version_and_other_parameters() {
4457        #[allow(dead_code)]
4458        #[derive(GenericOverIp)]
4459        #[generic_over_ip(I, Ip)]
4460        enum AddrOrDevice<I: Ip, D> {
4461            Addr(I::Addr),
4462            Device(D),
4463        }
4464        struct Device;
4465
4466        assert_ip_generic!(AddrOrDevice, Ip, Device);
4467    }
4468
4469    #[test]
4470    fn struct_with_ip_address_and_other_parameters() {
4471        #[allow(dead_code)]
4472        #[derive(GenericOverIp)]
4473        #[generic_over_ip(A, IpAddress)]
4474        struct AddrAndDevice<A: IpAddress, D> {
4475            addr: A,
4476            device: D,
4477        }
4478        struct Device;
4479
4480        assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4481    }
4482
4483    #[test]
4484    fn struct_with_unbounded_ip_address_and_other_parameters() {
4485        #[allow(dead_code)]
4486        #[derive(GenericOverIp)]
4487        #[generic_over_ip(A, IpAddress)]
4488        struct AddrAndDevice<A, D> {
4489            addr: A,
4490            device: D,
4491        }
4492        struct Device;
4493
4494        assert_ip_generic!(AddrAndDevice, IpAddress, Device);
4495    }
4496
4497    #[test]
4498    fn enum_with_ip_address_and_other_parameters() {
4499        #[allow(dead_code)]
4500        #[derive(GenericOverIp, Debug, PartialEq)]
4501        #[generic_over_ip(A, IpAddress)]
4502        enum AddrOrDevice<A: IpAddress, D> {
4503            Addr(A),
4504            Device(D),
4505        }
4506        struct Device;
4507
4508        assert_ip_generic!(AddrOrDevice, IpAddress, Device);
4509    }
4510
4511    #[test]
4512    fn struct_invariant_over_ip() {
4513        #[allow(dead_code)]
4514        #[derive(GenericOverIp)]
4515        #[generic_over_ip()]
4516        struct Invariant(usize);
4517
4518        assert_ip_generic!(Invariant);
4519    }
4520
4521    #[test]
4522    fn enum_invariant_over_ip() {
4523        #[allow(dead_code)]
4524        #[derive(GenericOverIp)]
4525        #[generic_over_ip()]
4526        enum Invariant {
4527            Usize(usize),
4528        }
4529
4530        assert_ip_generic!(Invariant);
4531    }
4532
4533    #[test]
4534    fn struct_invariant_over_ip_with_other_params() {
4535        #[allow(dead_code)]
4536        #[derive(GenericOverIp)]
4537        #[generic_over_ip()]
4538        struct Invariant<B, C, D>(B, C, D);
4539
4540        assert_ip_generic!(Invariant, usize, bool, char);
4541    }
4542
4543    #[test]
4544    fn enum_invariant_over_ip_with_other_params() {
4545        #[allow(dead_code)]
4546        #[derive(GenericOverIp)]
4547        #[generic_over_ip()]
4548        enum Invariant<A, B, C> {
4549            A(A),
4550            B(B),
4551            C(C),
4552        }
4553
4554        assert_ip_generic!(Invariant, usize, bool, char);
4555    }
4556
4557    #[test]
4558    fn struct_with_ip_version_extension_parameter() {
4559        trait FakeIpExt: Ip {
4560            type Associated;
4561        }
4562        impl FakeIpExt for Ipv4 {
4563            type Associated = u8;
4564        }
4565        impl FakeIpExt for Ipv6 {
4566            type Associated = u16;
4567        }
4568
4569        #[allow(dead_code)]
4570        #[derive(GenericOverIp)]
4571        #[generic_over_ip(I, Ip)]
4572        struct Generic<I: FakeIpExt> {
4573            field: I::Associated,
4574        }
4575
4576        assert_ip_generic!(Generic, Ip);
4577    }
4578
4579    #[test]
4580    fn struct_with_ip_version_extension_parameter_but_no_ip_bound() {
4581        trait FakeIpExt: Ip {
4582            type Associated;
4583        }
4584        impl FakeIpExt for Ipv4 {
4585            type Associated = u8;
4586        }
4587        impl FakeIpExt for Ipv6 {
4588            type Associated = u16;
4589        }
4590
4591        #[allow(dead_code)]
4592        #[derive(GenericOverIp)]
4593        #[generic_over_ip(I, Ip)]
4594        struct Generic<I: FakeIpExt> {
4595            field: I::Associated,
4596        }
4597
4598        assert_ip_generic!(Generic, Ip);
4599    }
4600
4601    #[test]
4602    fn struct_with_ip_address_extension_parameter() {
4603        trait FakeIpAddressExt: IpAddress {
4604            type Associated;
4605        }
4606        impl FakeIpAddressExt for Ipv4Addr {
4607            type Associated = u8;
4608        }
4609        impl FakeIpAddressExt for Ipv6Addr {
4610            type Associated = u16;
4611        }
4612
4613        #[allow(dead_code)]
4614        #[derive(GenericOverIp)]
4615        #[generic_over_ip(A, IpAddress)]
4616        struct Generic<A: IpAddress + FakeIpAddressExt> {
4617            field: A::Associated,
4618        }
4619
4620        assert_ip_generic!(Generic, IpAddress);
4621    }
4622
4623    #[test]
4624    fn type_with_lifetime_and_ip_parameter() {
4625        #[allow(dead_code)]
4626        #[derive(GenericOverIp)]
4627        #[generic_over_ip(I, Ip)]
4628        struct Generic<'a, I: Ip> {
4629            field: &'a I::Addr,
4630        }
4631
4632        assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv4, Generic<'static, Ipv4>>();
4633        assert_ip_generic_is::<Generic<'static, Ipv4>, Ipv6, Generic<'static, Ipv6>>();
4634        assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv4, Generic<'static, Ipv4>>();
4635        assert_ip_generic_is::<Generic<'static, Ipv6>, Ipv6, Generic<'static, Ipv6>>();
4636    }
4637
4638    #[test]
4639    fn type_with_lifetime_and_no_ip_parameter() {
4640        #[allow(dead_code)]
4641        #[derive(GenericOverIp)]
4642        #[generic_over_ip()]
4643        struct Generic<'a> {
4644            field: &'a (),
4645        }
4646
4647        assert_ip_generic_is::<Generic<'static>, Ipv4, Generic<'static>>();
4648        assert_ip_generic_is::<Generic<'static>, Ipv6, Generic<'static>>();
4649    }
4650
4651    #[test]
4652    fn type_with_params_list_with_trailing_comma() {
4653        trait IpExtensionTraitWithVeryLongName {}
4654        trait OtherIpExtensionTraitWithVeryLongName {}
4655        trait LongNameToForceFormatterToBreakLineAndAddTrailingComma {}
4656        // Regression test for https://fxbug.dev/42080215
4657        #[allow(dead_code)]
4658        #[derive(GenericOverIp)]
4659        #[generic_over_ip(I, Ip)]
4660        struct Generic<
4661            I: Ip
4662                + IpExtensionTraitWithVeryLongName
4663                + OtherIpExtensionTraitWithVeryLongName
4664                + LongNameToForceFormatterToBreakLineAndAddTrailingComma,
4665        > {
4666            field: I::Addr,
4667        }
4668    }
4669}