memory_addr/range.rs
1use core::{fmt, ops::Range};
2
3use crate::{MemoryAddr, PhysAddr, VirtAddr};
4
5/// A range of a given memory address type `A`.
6///
7/// The range is inclusive on the start and exclusive on the end. A range is
8/// considered **empty** iff `start == end`, and **invalid** iff `start > end`.
9/// An invalid range should not be created and cannot be obtained without unsafe
10/// operations, calling methods on an invalid range will cause unexpected
11/// consequences.
12///
13/// # Example
14///
15/// ```
16/// use memory_addr::AddrRange;
17///
18/// let range = AddrRange::<usize>::new(0x1000, 0x2000);
19/// assert_eq!(range.start, 0x1000);
20/// assert_eq!(range.end, 0x2000);
21/// ```
22#[derive(Clone, Copy, PartialEq, Eq)]
23pub struct AddrRange<A: MemoryAddr> {
24 /// The lower bound of the range (inclusive).
25 pub start: A,
26 /// The upper bound of the range (exclusive).
27 pub end: A,
28}
29
30/// Methods for [`AddrRange`].
31impl<A> AddrRange<A>
32where
33 A: MemoryAddr,
34{
35 /// Creates a new address range from the start and end addresses.
36 ///
37 /// # Panics
38 ///
39 /// Panics if `start > end`.
40 ///
41 /// # Example
42 ///
43 /// ```
44 /// use memory_addr::AddrRange;
45 ///
46 /// let range = AddrRange::new(0x1000usize, 0x2000);
47 /// assert_eq!(range.start, 0x1000);
48 /// assert_eq!(range.end, 0x2000);
49 /// ```
50 ///
51 /// And this will panic:
52 ///
53 /// ```should_panic
54 /// # use memory_addr::AddrRange;
55 /// let _ = AddrRange::new(0x2000usize, 0x1000);
56 /// ```
57 #[inline]
58 pub fn new(start: A, end: A) -> Self {
59 assert!(
60 start <= end,
61 "invalid `AddrRange`: {}..{}",
62 start.into(),
63 end.into()
64 );
65 Self { start, end }
66 }
67
68 /// Creates a new address range from the given range.
69 ///
70 /// Returns `None` if `start > end`.
71 ///
72 /// # Example
73 ///
74 /// ```
75 /// use memory_addr::AddrRange;
76 ///
77 /// let range = AddrRange::try_new(0x1000usize, 0x2000).unwrap();
78 /// assert_eq!(range.start, 0x1000);
79 /// assert_eq!(range.end, 0x2000);
80 /// assert!(AddrRange::try_new(0x2000usize, 0x1000).is_none());
81 /// ```
82 #[inline]
83 pub fn try_new(start: A, end: A) -> Option<Self> {
84 if start <= end {
85 Some(Self { start, end })
86 } else {
87 None
88 }
89 }
90
91 /// Creates a new address range from the given range without checking the
92 /// validity.
93 ///
94 /// # Safety
95 ///
96 /// The caller must ensure that `start <= end`, otherwise the range will be
97 /// invalid and unexpected consequences will occur.
98 ///
99 /// # Example
100 ///
101 /// ```
102 /// use memory_addr::AddrRange;
103 ///
104 /// let range = unsafe { AddrRange::new_unchecked(0x1000usize, 0x2000) };
105 /// assert_eq!(range.start, 0x1000);
106 /// assert_eq!(range.end, 0x2000);
107 /// ```
108 #[inline]
109 pub const unsafe fn new_unchecked(start: A, end: A) -> Self {
110 Self { start, end }
111 }
112
113 /// Creates a new address range from the start address and the size.
114 ///
115 /// # Panics
116 ///
117 /// Panics if `size` is too large and causes overflow during evaluating the
118 /// end address.
119 ///
120 /// # Example
121 ///
122 /// ```
123 /// use memory_addr::AddrRange;
124 ///
125 /// let range = AddrRange::from_start_size(0x1000usize, 0x1000);
126 /// assert_eq!(range.start, 0x1000);
127 /// assert_eq!(range.end, 0x2000);
128 /// ```
129 ///
130 /// And this will panic:
131 ///
132 /// ```should_panic
133 /// # use memory_addr::AddrRange;
134 /// let _ = AddrRange::from_start_size(0x1000usize, usize::MAX);
135 /// ```
136 #[inline]
137 pub fn from_start_size(start: A, size: usize) -> Self {
138 if let Some(end) = start.checked_add(size) {
139 Self { start, end }
140 } else {
141 panic!(
142 "size too large for `AddrRange`: {} + {}",
143 start.into(),
144 size
145 );
146 }
147 }
148
149 /// Creates a new address range from the start address and the size.
150 ///
151 /// Returns `None` if `size` is too large and causes overflow during
152 /// evaluating the end address.
153 ///
154 /// # Example
155 ///
156 /// ```
157 /// use memory_addr::AddrRange;
158 ///
159 /// let range = AddrRange::try_from_start_size(0x1000usize, 0x1000).unwrap();
160 /// assert_eq!(range.start, 0x1000);
161 /// assert_eq!(range.end, 0x2000);
162 /// assert!(AddrRange::try_from_start_size(0x1000usize, usize::MAX).is_none());
163 /// ```
164 #[inline]
165 pub fn try_from_start_size(start: A, size: usize) -> Option<Self> {
166 start.checked_add(size).map(|end| Self { start, end })
167 }
168
169 /// Creates a new address range from the start address and the size without
170 /// checking the validity.
171 ///
172 /// # Safety
173 ///
174 /// The caller must ensure that `size` is not too large and won't cause
175 /// overflow during evaluating the end address. Failing to do so will
176 /// create an invalid range and cause unexpected consequences.
177 ///
178 /// # Example
179 ///
180 /// ```
181 /// use memory_addr::AddrRange;
182 ///
183 /// let range = unsafe { AddrRange::from_start_size_unchecked(0x1000usize, 0x1000) };
184 /// assert_eq!(range.start, 0x1000);
185 /// assert_eq!(range.end, 0x2000);
186 /// ```
187 #[inline]
188 pub unsafe fn from_start_size_unchecked(start: A, size: usize) -> Self {
189 Self {
190 start,
191 end: start.wrapping_add(size),
192 }
193 }
194
195 /// Returns `true` if the range is empty.
196 ///
197 /// It's also guaranteed that `false` will be returned if the range is
198 /// invalid (i.e., `start > end`).
199 ///
200 /// # Example
201 ///
202 /// ```
203 /// use memory_addr::AddrRange;
204 ///
205 /// assert!(AddrRange::new(0x1000usize, 0x1000).is_empty());
206 /// assert!(!AddrRange::new(0x1000usize, 0x2000).is_empty());
207 /// ```
208 #[inline]
209 pub fn is_empty(self) -> bool {
210 self.start >= self.end
211 }
212
213 /// Returns the size of the range.
214 ///
215 /// # Example
216 ///
217 /// ```
218 /// use memory_addr::AddrRange;
219 ///
220 /// assert_eq!(AddrRange::new(0x1000usize, 0x1000).size(), 0);
221 /// assert_eq!(AddrRange::new(0x1000usize, 0x2000).size(), 0x1000);
222 /// ```
223 #[inline]
224 pub fn size(self) -> usize {
225 self.end.wrapping_sub_addr(self.start)
226 }
227
228 /// Checks if the range contains the given address.
229 ///
230 /// # Example
231 ///
232 /// ```
233 /// use memory_addr::AddrRange;
234 ///
235 /// let range = AddrRange::new(0x1000usize, 0x2000);
236 /// assert!(!range.contains(0x0fff));
237 /// assert!(range.contains(0x1000));
238 /// assert!(range.contains(0x1fff));
239 /// assert!(!range.contains(0x2000));
240 /// ```
241 #[inline]
242 pub fn contains(self, addr: A) -> bool {
243 self.start <= addr && addr < self.end
244 }
245
246 /// Checks if the range contains the given address range.
247 ///
248 /// # Example
249 ///
250 /// ```
251 /// use memory_addr::{addr_range, AddrRange};
252 ///
253 /// let range = AddrRange::new(0x1000usize, 0x2000);
254 /// assert!(!range.contains_range(addr_range!(0x0usize..0xfff)));
255 /// assert!(!range.contains_range(addr_range!(0x0fffusize..0x1fff)));
256 /// assert!(range.contains_range(addr_range!(0x1001usize..0x1fff)));
257 /// assert!(range.contains_range(addr_range!(0x1000usize..0x2000)));
258 /// assert!(!range.contains_range(addr_range!(0x1001usize..0x2001)));
259 /// assert!(!range.contains_range(addr_range!(0x2001usize..0x3001)));
260 /// ```
261 #[inline]
262 pub fn contains_range(self, other: Self) -> bool {
263 self.start <= other.start && other.end <= self.end
264 }
265
266 /// Checks if the range is contained in the given address range.
267 ///
268 /// # Example
269 ///
270 /// ```
271 /// use memory_addr::{addr_range, AddrRange};
272 ///
273 /// let range = AddrRange::new(0x1000usize, 0x2000);
274 /// assert!(!range.contained_in(addr_range!(0xfffusize..0x1fff)));
275 /// assert!(!range.contained_in(addr_range!(0x1001usize..0x2001)));
276 /// assert!(range.contained_in(addr_range!(0xfffusize..0x2001)));
277 /// assert!(range.contained_in(addr_range!(0x1000usize..0x2000)));
278 /// ```
279 #[inline]
280 pub fn contained_in(self, other: Self) -> bool {
281 other.contains_range(self)
282 }
283
284 /// Checks if the range overlaps with the given address range.
285 ///
286 /// # Example
287 ///
288 /// ```
289 /// use memory_addr::{addr_range, AddrRange};
290 ///
291 /// let range = AddrRange::new(0x1000usize, 0x2000usize);
292 /// assert!(!range.overlaps(addr_range!(0xfffusize..0xfff)));
293 /// assert!(!range.overlaps(addr_range!(0x2000usize..0x2000)));
294 /// assert!(!range.overlaps(addr_range!(0xfffusize..0x1000)));
295 /// assert!(range.overlaps(addr_range!(0xfffusize..0x1001)));
296 /// assert!(range.overlaps(addr_range!(0x1fffusize..0x2001)));
297 /// assert!(range.overlaps(addr_range!(0xfffusize..0x2001)));
298 /// ```
299 #[inline]
300 pub fn overlaps(self, other: Self) -> bool {
301 self.start < other.end && other.start < self.end
302 }
303}
304
305/// Conversion from [`Range`] to [`AddrRange`], provided that the type of the
306/// endpoints can be converted to the address type `A`.
307impl<A, T> TryFrom<Range<T>> for AddrRange<A>
308where
309 A: MemoryAddr + From<T>,
310{
311 type Error = ();
312
313 #[inline]
314 fn try_from(range: Range<T>) -> Result<Self, Self::Error> {
315 Self::try_new(range.start.into(), range.end.into()).ok_or(())
316 }
317}
318
319/// Implementations of [`Default`] for [`AddrRange`].
320///
321/// The default value is an empty range `Range { start: 0, end: 0 }`.
322impl<A> Default for AddrRange<A>
323where
324 A: MemoryAddr,
325{
326 #[inline]
327 fn default() -> Self {
328 Self {
329 start: 0.into(),
330 end: 0.into(),
331 }
332 }
333}
334
335/// Implementations of [`Debug`](fmt::Debug) for [`AddrRange`].
336impl<A> fmt::Debug for AddrRange<A>
337where
338 A: MemoryAddr + fmt::Debug,
339{
340 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
341 write!(f, "{:?}..{:?}", self.start, self.end)
342 }
343}
344
345/// Implementations of [`LowerHex`](fmt::LowerHex) for [`AddrRange`].
346impl<A> fmt::LowerHex for AddrRange<A>
347where
348 A: MemoryAddr + fmt::LowerHex,
349{
350 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
351 write!(f, "{:x}..{:x}", self.start, self.end)
352 }
353}
354
355/// Implementations of [`UpperHex`](fmt::UpperHex) for [`AddrRange`].
356impl<A> fmt::UpperHex for AddrRange<A>
357where
358 A: MemoryAddr + fmt::UpperHex,
359{
360 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
361 write!(f, "{:X}..{:X}", self.start, self.end)
362 }
363}
364
365/// A range of virtual addresses [`VirtAddr`].
366pub type VirtAddrRange = AddrRange<VirtAddr>;
367/// A range of physical addresses [`PhysAddr`].
368pub type PhysAddrRange = AddrRange<PhysAddr>;
369
370/// Converts the given range expression into [`AddrRange`]. Panics if the range
371/// is invalid.
372///
373/// The concrete address type is inferred from the context.
374///
375/// # Example
376///
377/// ```
378/// use memory_addr::{addr_range, AddrRange};
379///
380/// let range: AddrRange<usize> = addr_range!(0x1000usize..0x2000);
381/// assert_eq!(range.start, 0x1000usize);
382/// assert_eq!(range.end, 0x2000usize);
383/// ```
384///
385/// And this will panic:
386///
387/// ```should_panic
388/// # use memory_addr::{addr_range, AddrRange};
389/// let _: AddrRange<usize> = addr_range!(0x2000usize..0x1000);
390/// ```
391#[macro_export]
392macro_rules! addr_range {
393 ($range:expr) => {
394 $crate::AddrRange::try_from($range).expect("invalid address range in `addr_range!`")
395 };
396}
397
398/// Converts the given range expression into [`VirtAddrRange`]. Panics if the
399/// range is invalid.
400///
401/// # Example
402///
403/// ```
404/// use memory_addr::va_range;
405///
406/// let range = va_range!(0x1000..0x2000);
407/// assert_eq!(range.start, 0x1000.into());
408/// assert_eq!(range.end, 0x2000.into());
409/// ```
410///
411/// And this will panic:
412///
413/// ```should_panic
414/// # use memory_addr::va_range;
415/// let _ = va_range!(0x2000..0x1000);
416/// ```
417#[macro_export]
418macro_rules! va_range {
419 ($range:expr) => {
420 $crate::VirtAddrRange::try_from($range).expect("invalid address range in `va_range!`")
421 };
422}
423
424/// Converts the given range expression into [`PhysAddrRange`]. Panics if the
425/// range is invalid.
426///
427/// # Example
428///
429/// ```
430/// use memory_addr::pa_range;
431///
432/// let range = pa_range!(0x1000..0x2000);
433/// assert_eq!(range.start, 0x1000.into());
434/// assert_eq!(range.end, 0x2000.into());
435/// ```
436///
437/// And this will panic:
438///
439/// ```should_panic
440/// # use memory_addr::pa_range;
441/// let _ = pa_range!(0x2000..0x1000);
442/// ```
443#[macro_export]
444macro_rules! pa_range {
445 ($range:expr) => {
446 $crate::PhysAddrRange::try_from($range).expect("invalid address range in `pa_range!`")
447 };
448}
449
450#[cfg(test)]
451mod test {
452 use crate::{va, va_range, VirtAddrRange};
453
454 #[test]
455 fn test_range_format() {
456 let range = va_range!(0xfec000..0xfff000usize);
457
458 assert_eq!(format!("{:?}", range), "VA:0xfec000..VA:0xfff000");
459 assert_eq!(format!("{:x}", range), "VA:0xfec000..VA:0xfff000");
460 assert_eq!(format!("{:X}", range), "VA:0xFEC000..VA:0xFFF000");
461 }
462
463 #[test]
464 fn test_range() {
465 let start = va!(0x1000);
466 let end = va!(0x2000);
467 let range = va_range!(start..end);
468
469 println!("range: {:?}", range);
470
471 assert!((0x1000..0x1000).is_empty());
472 assert!((0x1000..0xfff).is_empty());
473 assert!(!range.is_empty());
474
475 assert_eq!(range.start, start);
476 assert_eq!(range.end, end);
477 assert_eq!(range.size(), 0x1000);
478
479 assert!(range.contains(va!(0x1000)));
480 assert!(range.contains(va!(0x1080)));
481 assert!(!range.contains(va!(0x2000)));
482
483 assert!(!range.contains_range(addr_range!(0xfff..0x1fff)));
484 assert!(!range.contains_range(addr_range!(0xfff..0x2000)));
485 assert!(!range.contains_range(va_range!(0xfff..0x2001))); // test both `va_range!` and `addr_range!`
486 assert!(range.contains_range(va_range!(0x1000..0x1fff)));
487 assert!(range.contains_range(addr_range!(0x1000..0x2000)));
488 assert!(!range.contains_range(addr_range!(0x1000..0x2001)));
489 assert!(range.contains_range(va_range!(0x1001..0x1fff)));
490 assert!(range.contains_range(va_range!(0x1001..0x2000)));
491 assert!(!range.contains_range(va_range!(0x1001..0x2001)));
492 assert!(!range.contains_range(VirtAddrRange::from_start_size(0xfff.into(), 0x1)));
493 assert!(!range.contains_range(VirtAddrRange::from_start_size(0x2000.into(), 0x1)));
494
495 assert!(range.contained_in(addr_range!(0xfff..0x2000)));
496 assert!(range.contained_in(addr_range!(0x1000..0x2000)));
497 assert!(range.contained_in(va_range!(0x1000..0x2001)));
498
499 assert!(!range.overlaps(addr_range!(0x800..0x1000)));
500 assert!(range.overlaps(addr_range!(0x800..0x1001)));
501 assert!(range.overlaps(addr_range!(0x1800..0x2000)));
502 assert!(range.overlaps(va_range!(0x1800..0x2001)));
503 assert!(!range.overlaps(va_range!(0x2000..0x2800)));
504 assert!(range.overlaps(va_range!(0xfff..0x2001)));
505
506 let default_range: VirtAddrRange = Default::default();
507 assert!(default_range.is_empty());
508 assert_eq!(default_range.size(), 0);
509 assert_eq!(default_range.start, va!(0));
510 assert_eq!(default_range.end, va!(0));
511 }
512}