ip/traits/prefix/
range.rs

1use core::fmt::{Debug, Display};
2use core::hash::Hash;
3use core::ops::RangeInclusive;
4use core::str::FromStr;
5
6use super::{Length, Prefix};
7use crate::{concrete, error::Error};
8
9/// Address-family independent interface for IP prefix ranges.
10///
11/// See also [`concrete::PrefixRange<A>`][crate::concrete::PrefixRange] and
12/// [`any::PrefixRange`][crate::any::PrefixRange] for address-family specific
13/// items.
14pub trait Range:
15    Clone
16    + Debug
17    + Display
18    + From<Self::Prefix>
19    + FromStr<Err = Error>
20    + Hash
21    + IntoIterator<Item = Self::Prefix>
22    + PartialEq
23    + Eq
24    + PartialOrd
25{
26    /// The type of IP prefix over which `Self` represents a range.
27    type Prefix: Prefix<Length = Self::Length>;
28
29    /// The type used to represent lengths for this IP prefix type.
30    type Length: Length;
31
32    /// Return the covering super-prefix of `self`.
33    fn prefix(&self) -> Self::Prefix;
34
35    /// Return the lower bound [`Self::Length`] of `self`.
36    fn lower(&self) -> Self::Length;
37
38    /// Return the upper bound [`Self::Length`] of `self`.
39    fn upper(&self) -> Self::Length;
40
41    /// Construct a new IP prefix-range from the intersection of `self` and
42    /// `len_range`.
43    ///
44    /// # Examples
45    ///
46    /// ```
47    /// use ip::{traits::PrefixRange as _, Ipv6, Prefix, PrefixLength, PrefixRange};
48    ///
49    /// let lower = PrefixLength::<Ipv6>::from_primitive(52)?;
50    /// let upper = PrefixLength::<Ipv6>::from_primitive(56)?;
51    ///
52    /// let x: PrefixRange<Ipv6> = "2001:db8::/48".parse::<Prefix<Ipv6>>()?.into();
53    /// assert_eq!(x.with_intersection(lower..=upper).into_iter().count(), 0,);
54    ///
55    /// let y: PrefixRange<Ipv6> = "2001:db8::/54".parse::<Prefix<Ipv6>>()?.into();
56    /// assert_eq!(y.with_intersection(lower..=upper).into_iter().count(), 1,);
57    /// # Ok::<(), ip::Error>(())
58    /// ```
59    fn with_intersection(self, len_range: RangeInclusive<Self::Length>) -> Option<Self>;
60
61    /// Construct a new IP prefix-range consisting of all the more specific
62    /// sub-prefixes of `self` with prefix-lengths within `len_range`.
63    ///
64    /// # Examples
65    ///
66    /// ```
67    /// use core::cmp::max;
68    ///
69    /// use ip::{traits::PrefixRange as _, Address, Ipv4, Prefix, PrefixLength, PrefixRange};
70    ///
71    /// let addr = "192.0.2.0".parse::<Address<Ipv4>>()?;
72    ///
73    /// let [l, m, n, p, q]: &[PrefixLength<Ipv4>] = &[24u8, 26, 28, 30, 32]
74    ///     .into_iter()
75    ///     .map(PrefixLength::<Ipv4>::from_primitive)
76    ///     .collect::<Result<Vec<PrefixLength<Ipv4>>, _>>()?
77    /// else {
78    ///     panic!()
79    /// };
80    ///
81    /// let prefix = Prefix::<Ipv4>::new(addr, *l);
82    ///
83    /// assert_eq!(
84    ///     PrefixRange::<Ipv4>::new(prefix, *m..=*n)?
85    ///         .with_length_range(*p..=*q)
86    ///         .unwrap(),
87    ///     PrefixRange::<Ipv4>::new(prefix, max(*m, *p)..=*q)?,
88    /// );
89    /// # Ok::<(), ip::Error>(())
90    /// ```
91    fn with_length_range(self, len_range: RangeInclusive<Self::Length>) -> Option<Self>;
92
93    /// Construct a new IP prefix-range consisting of all the more-specific
94    /// sub-prefixes of `self`.
95    ///
96    /// # Examples
97    ///
98    /// ```
99    /// use ip::{traits::PrefixRange as _, Any, Prefix, PrefixRange};
100    ///
101    /// let range: PrefixRange<Any> = "2001:db8::/126".parse::<Prefix<Any>>()?.into();
102    ///
103    /// assert_eq!(range.or_longer().into_iter().count(), 7,);
104    /// # Ok::<(), ip::Error>(())
105    /// ```
106    #[must_use]
107    fn or_longer(self) -> Self {
108        let lower = self.lower();
109        let upper = self.prefix().max_prefix_len();
110        // OK to unwrap here as we can guarantee that `len_range` in non-empty.
111        self.with_length_range(lower..=upper).unwrap()
112    }
113
114    /// Construct a new IP prefix-range consisting of all the *strictly*
115    /// more-specific sub-prefixes of `self`.
116    ///
117    /// # Examples
118    ///
119    /// ```
120    /// use ip::{traits::PrefixRange as _, Any, Prefix, PrefixRange};
121    ///
122    /// let x: PrefixRange<Any> = "192.0.2.0/24,25,27".parse()?;
123    /// let y: PrefixRange<Any> = "192.0.2.0/24,26,32".parse()?;
124    ///
125    /// assert_eq!(x.or_longer_excl().unwrap(), y);
126    /// # Ok::<(), ip::Error>(())
127    /// ```
128    fn or_longer_excl(self) -> Option<Self> {
129        let lower = self.lower().increment().ok()?;
130        let upper = self.prefix().max_prefix_len();
131        self.with_length_range(lower..=upper)
132    }
133
134    /// Construct a new IP prefix-range consisting of all the more-specific
135    /// sub-prefixes of `self` of length `len`.
136    ///
137    /// # Examples
138    ///
139    /// ```
140    /// use ip::{traits::PrefixRange as _, Any, Ipv6, Prefix, PrefixLength, PrefixRange};
141    ///
142    /// let range: PrefixRange<Any> = "2001:db8::/32".parse::<Prefix<Any>>()?.into();
143    /// let len = PrefixLength::<Ipv6>::from_primitive(48)?.into();
144    ///
145    /// assert_eq!(range.with_length(len).unwrap().into_iter().count(), 1 << 16,);
146    /// # Ok::<(), ip::Error>(())
147    /// ```
148    fn with_length(self, len: Self::Length) -> Option<Self> {
149        self.with_length_range(len..=len)
150    }
151
152    /// Returns the address-family associated with this IP prefix-range.
153    ///
154    /// # Examples
155    ///
156    /// ```
157    /// use ip::{traits::PrefixRange as _, Any, PrefixRange};
158    ///
159    /// let range: PrefixRange<Any> = "2001:db8::/32,48,64".parse()?;
160    ///
161    /// assert_eq!(range.afi().to_string(), "ipv6");
162    /// # Ok::<(), ip::Error>(())
163    /// ```
164    fn afi(&self) -> concrete::Afi {
165        self.prefix().afi()
166    }
167
168    /// Try to construct a new [`Self::Length`] for the address-family
169    /// associated with this IP prefix-range.
170    ///
171    /// # Errors
172    ///
173    /// Fails when `length` is outside of the bounds of prefix-lengths of the
174    /// address-family.
175    ///
176    /// # Examples
177    ///
178    /// ```
179    /// use ip::{traits::PrefixRange as _, Any, Ipv4, PrefixLength, PrefixRange};
180    ///
181    /// let range: PrefixRange<Any> = "192.0.2.0/24,26,28".parse()?;
182    ///
183    /// assert_eq!(
184    ///     range.new_prefix_length(30)?,
185    ///     PrefixLength::<Ipv4>::from_primitive(30)?.into(),
186    /// );
187    /// # Ok::<(), ip::Error>(())
188    /// ```
189    fn new_prefix_length(&self, length: u8) -> Result<Self::Length, Error> {
190        self.prefix().new_prefix_length(length)
191    }
192}