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}