ip/concrete/prefix/
subprefixes.rs1use super::{Bitmask, Hostmask, Netmask, Prefix, PrefixLength};
2use crate::{
3 error::{err, Error, Kind},
4 traits::{Afi, Prefix as _, PrefixLength as _},
5};
6
7#[derive(Debug, Clone)]
9pub struct Subprefixes<A: Afi> {
10 base: Prefix<A>,
11 next: Option<Prefix<A>>,
12 step: Option<Bitmask<A>>,
13}
14
15impl<A: Afi> Subprefixes<A> {
16 pub(super) fn new(base: Prefix<A>, length: PrefixLength<A>) -> Result<Self, Error> {
17 if length < base.length() {
18 Err(err!(Kind::PrefixLength))
19 } else {
20 let next = Some(Prefix::new(base.prefix(), length));
21 let step = length
22 .decrement()
23 .map(Hostmask::from)
24 .map(|hostbits| hostbits & Netmask::from(length))
25 .ok();
26 Ok(Self { base, next, step })
27 }
28 }
29}
30
31impl<A: Afi> Iterator for Subprefixes<A> {
32 type Item = Prefix<A>;
33
34 fn next(&mut self) -> Option<Self::Item> {
35 if let Some(next) = self.next.take() {
36 self.next = self
37 .step
38 .and_then(|step| next.map_addr(|addr| addr + step))
39 .filter(|prefix| self.base.contains(prefix));
40 Some(next)
41 } else {
42 None
43 }
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use crate::{traits::Prefix as _, Any, Ipv4, Ipv6, Prefix};
50
51 #[test]
52 fn singleton_subprefix_ipv4() {
53 let p: Prefix<Ipv4> = "192.0.2.0/24".parse().unwrap();
54 let mut subprefixes = p.subprefixes(p.prefix_len()).unwrap();
55 assert_eq!(subprefixes.next(), Some(p));
56 assert_eq!(subprefixes.next(), None);
57 }
58
59 #[test]
60 fn singleton_subprefix_ipv6() {
61 let p: Prefix<Ipv6> = "2001:db8::/48".parse().unwrap();
62 let mut subprefixes = p.subprefixes(p.prefix_len()).unwrap();
63 assert_eq!(subprefixes.next(), Some(p));
64 assert_eq!(subprefixes.next(), None);
65 }
66
67 #[test]
68 fn singleton_subprefix_any() {
69 let p: Prefix<Any> = "2001:db8:f00::/64".parse().unwrap();
70 let mut subprefixes = p.subprefixes(p.prefix_len()).unwrap();
71 assert_eq!(subprefixes.next(), Some(p));
72 assert_eq!(subprefixes.next(), None);
73 }
74
75 #[test]
76 fn count_subprefixes_of_default() {
77 let p: Prefix<Ipv4> = "0.0.0.0/0".parse().unwrap();
78 let len = p.new_prefix_length(8).unwrap();
79 assert_eq!(p.subprefixes(len).unwrap().count(), 256);
80 }
81}