netaddr2/netv4addr/
merge.rs1use super::Netv4Addr;
2use crate::traits::Merge;
3use core::cmp::Ordering;
4use std::net::Ipv4Addr;
5
6impl Merge for Netv4Addr {
7 type Output = Option<Self>;
8
9 fn merge(&self, other: &Self) -> Self::Output {
10 let addr: u32 = self.addr().into();
11 let mask: u32 = self.mask().into();
12 let other_addr: u32 = other.addr().into();
13 let other_mask: u32 = other.mask().into();
14
15 let mask: u32 = match mask.cmp(&other_mask) {
16 Ordering::Equal => mask << 1,
17 Ordering::Less => mask,
18 Ordering::Greater => other_mask,
19 };
20
21 if addr & mask == other_addr & mask {
22 Some(Self::new(Ipv4Addr::from(addr & mask), Ipv4Addr::from(mask)))
23 } else {
24 None
25 }
26 }
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 #[test]
34 fn mergeable_networks_correct() {
35 let a: Netv4Addr = "10.0.0.0/24".parse().unwrap();
36 let b: Netv4Addr = "10.0.1.0/24".parse().unwrap();
37
38 assert_eq!(a.merge(&b), Some("10.0.0.0/23".parse().unwrap()));
39 }
40
41 #[test]
42 fn mergeable_networks_reflexive() {
43 let a: Netv4Addr = "10.0.0.0/24".parse().unwrap();
44 let b: Netv4Addr = "10.0.1.0/24".parse().unwrap();
45
46 assert_eq!(a.merge(&b), b.merge(&a));
47 }
48
49 #[test]
50 fn nested_networks_takes_biggest() {
51 let a: Netv4Addr = "10.0.0.0/24".parse().unwrap();
52 let b: Netv4Addr = "10.0.0.0/23".parse().unwrap();
53
54 assert_eq!(a.merge(&b), Some(b));
55 }
56
57 #[test]
58 fn nested_networks_reflexive() {
59 let a: Netv4Addr = "10.0.0.0/24".parse().unwrap();
60 let b: Netv4Addr = "10.0.0.0/23".parse().unwrap();
61
62 assert_eq!(a.merge(&b), b.merge(&a));
63 }
64
65 #[test]
66 fn adjacent_but_not_mergable_none() {
67 let a: Netv4Addr = "10.0.1.0/24".parse().unwrap();
68 let b: Netv4Addr = "10.0.2.0/24".parse().unwrap();
69
70 assert_eq!(a.merge(&b), None);
71 assert_eq!(b.merge(&a), None);
72 assert_eq!(a.merge(&b), b.merge(&a));
73 }
74}