1use std::cmp::Ordering;
5
6use crate::bus::{BusAddress, Error, MmioAddress, PioAddress};
7
8#[derive(Copy, Clone, Debug)]
10pub struct BusRange<A: BusAddress> {
11 base: A,
12 size: A::V,
13}
14
15impl<A: BusAddress> BusRange<A> {
16 pub fn new(base: A, size: A::V) -> Result<Self, Error> {
18 if size == 0.into() {
20 return Err(Error::InvalidRange);
21 }
22
23 base.checked_add(size - 1.into())
26 .ok_or(Error::InvalidRange)?;
27
28 Ok(BusRange { base, size })
29 }
30
31 pub fn unit(base: A) -> Self {
33 BusRange {
34 base,
35 size: 1.into(),
36 }
37 }
38
39 pub fn base(&self) -> A {
41 self.base
42 }
43
44 pub fn size(&self) -> A::V {
46 self.size
47 }
48
49 pub fn last(&self) -> A {
51 self.base + (self.size - 1.into())
52 }
53
54 pub fn overlaps(&self, other: &BusRange<A>) -> bool {
56 !(self.base > other.last() || self.last() < other.base)
57 }
58}
59
60impl<A: BusAddress> PartialEq for BusRange<A> {
66 fn eq(&self, other: &BusRange<A>) -> bool {
67 self.base == other.base
68 }
69}
70
71impl<A: BusAddress> Eq for BusRange<A> {}
72
73impl<A: BusAddress> PartialOrd for BusRange<A> {
74 fn partial_cmp(&self, other: &BusRange<A>) -> Option<Ordering> {
75 self.base.partial_cmp(&other.base)
76 }
77}
78
79impl<A: BusAddress> Ord for BusRange<A> {
80 fn cmp(&self, other: &BusRange<A>) -> Ordering {
81 self.base.cmp(&other.base)
82 }
83}
84
85pub type MmioRange = BusRange<MmioAddress>;
87pub type PioRange = BusRange<PioAddress>;
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_bus_range() {
96 let base_zero = MmioAddress(0);
97 let value = 5;
98
99 assert_eq!(BusRange::new(base_zero, 0), Err(Error::InvalidRange));
100
101 assert!(BusRange::new(base_zero, std::u64::MAX).is_ok());
102 assert!(BusRange::new(MmioAddress(1), std::u64::MAX).is_ok());
103 assert_eq!(
104 BusRange::new(MmioAddress(2), std::u64::MAX),
105 Err(Error::InvalidRange)
106 );
107
108 {
109 let range = BusRange::new(base_zero, value).unwrap();
110 assert_eq!(range.base(), base_zero);
111 assert_eq!(range.size(), value);
112 assert_eq!(range.last(), MmioAddress(value - 1));
113 assert!(range.base() < range.last());
114 }
115
116 {
117 let range = BusRange::unit(base_zero);
118 assert_eq!(range.base(), base_zero);
119 assert_eq!(range.last(), range.base());
120 }
121
122 {
124 let range = BusRange::new(MmioAddress(10), 10).unwrap();
125
126 let overlaps = |base_value, len_value| {
127 range.overlaps(&BusRange::new(MmioAddress(base_value), len_value).unwrap())
128 };
129
130 assert!(!overlaps(0, 5));
131 assert!(!overlaps(0, 10));
132 assert!(!overlaps(5, 5));
133
134 assert!(overlaps(0, 11));
135 assert!(overlaps(5, 6));
136 assert!(overlaps(5, 10));
137 assert!(overlaps(11, 15));
138 assert!(overlaps(5, 35));
139 assert!(overlaps(19, 1));
140 assert!(overlaps(19, 10));
141
142 assert!(!overlaps(20, 1));
143 assert!(!overlaps(30, 10));
144 }
145
146 {
148 let base = MmioAddress(10);
149 let len = 10;
150
151 let range = BusRange::new(base, len).unwrap();
152
153 assert_eq!(range.cmp(&range), range.partial_cmp(&range).unwrap());
154 assert_eq!(range.cmp(&range), Ordering::Equal);
155
156 {
157 let other = BusRange::new(base, len + 1).unwrap();
158
159 assert_eq!(range, other);
162
163 assert_eq!(range.cmp(&other), range.partial_cmp(&other).unwrap());
164 assert_eq!(range.cmp(&other), Ordering::Equal);
165 }
166
167 {
168 let other = BusRange::unit(base.checked_add(1).unwrap());
169
170 assert_ne!(range, other);
172
173 assert_eq!(range.cmp(&other), range.partial_cmp(&other).unwrap());
174 assert_eq!(range.cmp(&other), Ordering::Less);
175 }
176 }
177 }
178}