ip/traits/prefix/mod.rs
1use core::fmt::{Debug, Display};
2use core::hash::Hash;
3use core::str::FromStr;
4
5use super::{Address, Mask};
6use crate::{concrete, error::Error};
7
8mod len;
9pub use self::len::Length;
10
11mod range;
12pub use self::range::Range;
13
14mod set;
15pub use self::set::Set;
16
17/// Address-family independent interface for IP prefixes
18///
19/// Methods on `Prefix` types that are well defined for all address-families
20/// are implemented via this trait.
21///
22/// In general, methods on this trait have signatures and semantics compatible
23/// with methods of the same names on the [`ipnet`] network types. Where
24/// there is deviation, this is noted in the method documentation.
25///
26/// See also [`concrete::Prefix<A>`][crate::concrete::Prefix] and
27/// [`any::Prefix`][crate::any::Prefix] for address-family specific items.
28pub trait Prefix:
29 Sized + Copy + Clone + Debug + Display + FromStr<Err = Error> + Hash + PartialEq + Eq + PartialOrd
30{
31 /// The type of IP address represented by this prefix type.
32 type Address: Address;
33
34 /// The type used to represent lengths for this IP prefix type.
35 type Length: Length;
36
37 /// The type of IP hostmask corresponding to this prefix type.
38 type Hostmask: Mask;
39
40 /// The type of IP netmask corresponding to this prefix type.
41 type Netmask: Mask;
42
43 /// The [`Iterator`] type returned by the [`Self::subprefixes`] method.
44 type Subprefixes: Iterator<Item = Self>;
45 // TODO:
46 // type Hosts: Iterator<Item = Self::Address>;
47
48 /// Returns the network address of the IP subnet represented by this
49 /// prefix.
50 ///
51 /// # Examples
52 ///
53 /// ``` rust
54 /// use ip::{traits::Prefix as _, Address, Any, Ipv4, Ipv6, Prefix};
55 ///
56 /// assert_eq!(
57 /// "172.16.123.123/16".parse::<Prefix<Ipv4>>()?.network(),
58 /// "172.16.0.0".parse::<Address<Ipv4>>()?,
59 /// );
60 ///
61 /// assert_eq!(
62 /// "2001:db8:f00::/48".parse::<Prefix<Ipv6>>()?.network(),
63 /// "2001:db8:f00::".parse::<Address<Ipv6>>()?,
64 /// );
65 ///
66 /// assert_eq!(
67 /// "10.255.0.0/16".parse::<Prefix<Any>>()?.network(),
68 /// Address::<Any>::Ipv4("10.255.0.0".parse()?),
69 /// );
70 /// # Ok::<(), ip::Error>(())
71 /// ```
72 fn network(&self) -> Self::Address;
73
74 /// Returns the hostmask of the IP subnet represented by this prefix.
75 ///
76 /// # Examples
77 ///
78 /// ``` rust
79 /// use ip::{traits::Prefix as _, Ipv4, Prefix};
80 ///
81 /// assert_eq!(
82 /// "172.16.123.123/16"
83 /// .parse::<Prefix<Ipv4>>()?
84 /// .hostmask()
85 /// .to_string(),
86 /// "0.0.255.255",
87 /// );
88 /// # Ok::<(), ip::Error>(())
89 /// ```
90 fn hostmask(&self) -> Self::Hostmask;
91
92 /// Returns the netmask of the IP subnet represented by this prefix.
93 ///
94 /// # Examples
95 ///
96 /// ``` rust
97 /// use ip::{traits::Prefix as _, Ipv4, Prefix};
98 ///
99 /// assert_eq!(
100 /// "172.16.123.123/16"
101 /// .parse::<Prefix<Ipv4>>()?
102 /// .netmask()
103 /// .to_string(),
104 /// "255.255.0.0",
105 /// );
106 /// # Ok::<(), ip::Error>(())
107 /// ```
108 fn netmask(&self) -> Self::Netmask;
109
110 /// Returns the maximum valid prefix length for prefixes of this type.
111 ///
112 /// # Examples
113 ///
114 /// ``` rust
115 /// use ip::{traits::Prefix as _, Any, Ipv4, Ipv6, Prefix, PrefixLength};
116 ///
117 /// assert_eq!(
118 /// "172.16.123.123/16".parse::<Prefix<Any>>()?.max_prefix_len(),
119 /// PrefixLength::<Ipv4>::MAX.into(),
120 /// );
121 ///
122 /// assert_eq!(
123 /// "2001:db8:f00::/48".parse::<Prefix<Any>>()?.max_prefix_len(),
124 /// PrefixLength::<Ipv6>::MAX.into(),
125 /// );
126 /// # Ok::<(), ip::Error>(())
127 /// ```
128 fn max_prefix_len(&self) -> Self::Length;
129
130 /// Returns the length of this prefix.
131 ///
132 /// # Examples
133 ///
134 /// ``` rust
135 /// use ip::{traits::Prefix as _, Ipv4, Ipv6, Prefix, PrefixLength};
136 ///
137 /// assert_eq!(
138 /// "172.16.123.123/16".parse::<Prefix<Ipv4>>()?.prefix_len(),
139 /// PrefixLength::<Ipv4>::from_primitive(16)?,
140 /// );
141 ///
142 /// assert_eq!(
143 /// "2001:db8:f00::/48".parse::<Prefix<Ipv6>>()?.prefix_len(),
144 /// PrefixLength::<Ipv6>::from_primitive(48)?,
145 /// );
146 /// # Ok::<(), ip::Error>(())
147 /// ```
148 fn prefix_len(&self) -> Self::Length;
149
150 /// Returns the broadcast address of the IP subnet represented by this
151 /// prefix.
152 ///
153 /// # [`ipnet`] Compatibility
154 ///
155 /// The term "broadcast address" has no meaning when applied to IPv6
156 /// subnets. However, for compatibility with [`ipnet::Ipv6Net`], this
157 /// method will return the last address covered by the prefix in all
158 /// cases.
159 ///
160 /// # Examples
161 ///
162 /// ``` rust
163 /// use ip::{traits::Prefix as _, Address, Any, Ipv4, Ipv6, Prefix};
164 ///
165 /// assert_eq!(
166 /// "172.16.123.123/16".parse::<Prefix<Ipv4>>()?.broadcast(),
167 /// "172.16.255.255".parse::<Address<Ipv4>>()?,
168 /// );
169 ///
170 /// assert_eq!(
171 /// "2001:db8:f00::/48".parse::<Prefix<Ipv6>>()?.broadcast(),
172 /// "2001:db8:f00:ffff:ffff:ffff:ffff:ffff".parse::<Address<Ipv6>>()?,
173 /// );
174 ///
175 /// assert_eq!(
176 /// "2001:db8:dead:beef::/64"
177 /// .parse::<Prefix<Any>>()?
178 /// .broadcast(),
179 /// Address::<Any>::Ipv6("2001:db8:dead:beef:ffff:ffff:ffff:ffff".parse()?),
180 /// );
181 /// # Ok::<(), ip::Error>(())
182 /// ```
183 fn broadcast(&self) -> Self::Address;
184
185 /// Returns the prefix of length `self.prefix_len() + 1` containing `self`,
186 /// if it exists.
187 ///
188 /// # Examples
189 ///
190 /// ``` rust
191 /// use ip::{traits::Prefix as _, Ipv4, Ipv6, Prefix};
192 ///
193 /// assert_eq!(
194 /// "172.16.123.123/16".parse::<Prefix<Ipv4>>()?.supernet(),
195 /// Some("172.16.0.0/15".parse()?),
196 /// );
197 ///
198 /// assert_eq!("::/0".parse::<Prefix<Ipv6>>()?.supernet(), None,);
199 /// # Ok::<(), ip::Error>(())
200 /// ```
201 fn supernet(&self) -> Option<Self>;
202
203 /// Returns [`true`] if `self` and `other` share the same immediate
204 /// supernet. See also [`supernet()`][Self::supernet()].
205 ///
206 /// # Examples
207 ///
208 /// ``` rust
209 /// use ip::{traits::Prefix as _, Ipv6, Prefix};
210 ///
211 /// let a: Prefix<Ipv6> = "2001:db8:a::/48".parse()?;
212 /// let b: Prefix<Ipv6> = "2001:db8:b::/48".parse()?;
213 /// let c: Prefix<Ipv6> = "2001:db8:c::/48".parse()?;
214 ///
215 /// assert!(a.is_sibling(&b));
216 /// assert!(!b.is_sibling(&c));
217 /// # Ok::<(), ip::Error>(())
218 /// ```
219 fn is_sibling(&self, other: &Self) -> bool;
220
221 /// Returns [`true`] if `self` contains `other` (in the set-theoretic
222 /// sense).
223 ///
224 /// # Note
225 ///
226 /// This method is defined for all types `T` where `Self: PartialOrd<T>`.
227 ///
228 /// # Examples
229 ///
230 /// ``` rust
231 /// use ip::{traits::Prefix as _, Address, Ipv6, Prefix};
232 ///
233 /// let a: Prefix<Ipv6> = "2001:db8:a::/48".parse()?;
234 /// let b: Prefix<Ipv6> = "2001:db8:a:b::/64".parse()?;
235 /// let c: Prefix<Ipv6> = "2001:db8::/32".parse()?;
236 ///
237 /// assert!(a.contains(&b));
238 /// assert!(!a.contains(&c));
239 ///
240 /// let x: Address<Ipv6> = "2001:db8:a::1".parse()?;
241 /// let y: Address<Ipv6> = "2001:db8::1".parse()?;
242 ///
243 /// assert!(a.contains(&x));
244 /// assert!(!a.contains(&y));
245 /// # Ok::<(), ip::Error>(())
246 /// ```
247 fn contains<T>(&self, other: &T) -> bool
248 where
249 Self: PartialOrd<T>,
250 {
251 self.ge(other)
252 }
253
254 // TODO:
255 // #[cfg(feature = "std")]
256 // fn aggregate(networks: &std::vec::Vec<Self>) -> std::vec::Vec<Self>;
257 // fn hosts(&self) -> Self::Hosts;
258
259 /// Returns an iterator over the subprefixes of `self` of length
260 /// `new_prefix_len`.
261 ///
262 /// # Errors
263 ///
264 /// An error is returned if `new_prefix_len < self.prefix_len()`.
265 ///
266 /// # Examples
267 ///
268 /// ``` rust
269 /// use ip::{traits::Prefix as _, Ipv4, Ipv6, Prefix, PrefixLength};
270 ///
271 /// let prefix: Prefix<Ipv4> = "192.0.2.0/24".parse()?;
272 /// let new_length = PrefixLength::<Ipv4>::from_primitive(26)?;
273 ///
274 /// assert_eq!(prefix.subprefixes(new_length)?.count(), 4);
275 /// # Ok::<(), ip::Error>(())
276 /// ```
277 fn subprefixes(&self, new_prefix_len: Self::Length) -> Result<Self::Subprefixes, Error>;
278
279 /// Returns the address-family associated with this IP prefix.
280 ///
281 /// # Examples
282 ///
283 /// ```
284 /// use ip::{traits::Prefix as _, Any, Prefix};
285 ///
286 /// let prefix: Prefix<Any> = "192.0.2.0/24".parse()?;
287 ///
288 /// assert_eq!(prefix.afi().to_string(), "ipv4");
289 /// # Ok::<(), ip::Error>(())
290 /// ```
291 fn afi(&self) -> concrete::Afi {
292 self.network().afi()
293 }
294
295 /// Try to construct a new [`Self::Length`] for the address-family
296 /// associated with this IP prefix.
297 ///
298 /// # Errors
299 ///
300 /// Fails when `length` is outside of the bounds of prefix-lengths of the
301 /// address-family.
302 ///
303 /// # Examples
304 ///
305 /// ```
306 /// use ip::{traits::Prefix as _, Any, Ipv6, Prefix, PrefixLength};
307 ///
308 /// let prefix: Prefix<Any> = "2001:db8::/32".parse()?;
309 ///
310 /// assert_eq!(
311 /// prefix.new_prefix_length(48)?,
312 /// PrefixLength::<Ipv6>::from_primitive(48)?.into(),
313 /// );
314 /// # Ok::<(), ip::Error>(())
315 /// ```
316 // #[cfg(feature = "std")]
317 fn new_prefix_length(&self, length: u8) -> Result<Self::Length, Error>;
318}