mm1_address/
address_range.rs1use std::fmt;
2
3use crate::address::Address;
4use crate::subnet::{NetAddress, NetMask};
5
6#[derive(Debug, Clone, Copy)]
24pub struct AddressRange {
25 lo: Address,
26 hi: Address,
27}
28
29impl AddressRange {
30 fn new(lo: Address, hi: Address) -> Self {
31 debug_assert!(lo <= hi, "AddressRange lo must not exceed hi: {lo}-{hi}");
32 Self { lo, hi }
33 }
34
35 pub fn lo(&self) -> Address {
36 self.lo
37 }
38
39 pub fn hi(&self) -> Address {
40 self.hi
41 }
42}
43
44impl From<Address> for AddressRange {
45 fn from(addr: Address) -> Self {
46 Self::new(addr, addr)
47 }
48}
49impl From<NetAddress> for AddressRange {
50 fn from(net: NetAddress) -> Self {
51 let lo = net.address;
52 let hi = Address::from_u64(net.address.into_u64() | !net.mask.into_u64());
53
54 Self::new(lo, hi)
55 }
56}
57
58impl From<AddressRange> for NetAddress {
59 fn from(range: AddressRange) -> Self {
60 let AddressRange { lo, hi } = range;
61 let address = lo;
62 let mask_bits = !(lo.into_u64() ^ hi.into_u64());
63 let mask = NetMask::try_from(mask_bits.leading_ones() as u8).expect("should be fine");
64 Self { address, mask }
65 }
66}
67
68impl Ord for AddressRange {
69 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
70 use std::cmp::Ordering::*;
71
72 match (self.hi.cmp(&other.lo), self.lo.cmp(&other.hi)) {
75 (Less, Less) => Less,
76 (Greater, Greater) => Greater,
77 (..) => Equal,
78 }
79 }
80}
81impl PartialEq for AddressRange {
82 fn eq(&self, other: &Self) -> bool {
83 Ord::cmp(self, other).is_eq()
84 }
85}
86impl Eq for AddressRange {}
87impl PartialOrd for AddressRange {
88 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
89 Some(Ord::cmp(self, other))
90 }
91}
92
93impl fmt::Display for AddressRange {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 write!(f, "{}-{}", self.lo, self.hi)
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 fn range(lo: u64, hi: u64) -> AddressRange {
104 AddressRange::new(Address::from_u64(lo), Address::from_u64(hi))
105 }
106
107 #[test]
110 fn ordering_semantics() {
111 use std::cmp::Ordering::*;
112
113 assert_eq!(range(5, 5).cmp(&range(0, 10)), Equal);
115 assert_eq!(range(0, 10).cmp(&range(5, 5)), Equal);
116
117 assert_eq!(range(0, 10).cmp(&range(11, 20)), Less);
119 assert_eq!(range(11, 20).cmp(&range(0, 10)), Greater);
120
121 assert_eq!(range(0, 10).cmp(&range(10, 20)), Equal);
123 }
124}