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}