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}