Skip to main content

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