memory_addr/
iter.rs

1use crate::MemoryAddr;
2
3/// A page-by-page iterator.
4///
5/// The page size is specified by the generic parameter `PAGE_SIZE`, which must
6/// be a power of 2.
7///
8/// The address type is specified by the type parameter `A`.
9///
10/// # Examples
11///
12/// ```
13/// use memory_addr::PageIter;
14///
15/// let mut iter = PageIter::<0x1000, usize>::new(0x1000, 0x3000).unwrap();
16/// assert_eq!(iter.next(), Some(0x1000));
17/// assert_eq!(iter.next(), Some(0x2000));
18/// assert_eq!(iter.next(), None);
19///
20/// assert!(PageIter::<0x1000, usize>::new(0x1000, 0x3001).is_none());
21/// ```
22pub struct PageIter<const PAGE_SIZE: usize, A>
23where
24    A: MemoryAddr,
25{
26    start: A,
27    end: A,
28}
29
30impl<A, const PAGE_SIZE: usize> PageIter<PAGE_SIZE, A>
31where
32    A: MemoryAddr,
33{
34    /// Creates a new [`PageIter`].
35    ///
36    /// Returns `None` if `PAGE_SIZE` is not a power of 2, or `start` or `end`
37    /// is not page-aligned.
38    pub fn new(start: A, end: A) -> Option<Self> {
39        if !PAGE_SIZE.is_power_of_two()
40            || !start.is_aligned(PAGE_SIZE)
41            || !end.is_aligned(PAGE_SIZE)
42        {
43            None
44        } else {
45            Some(Self { start, end })
46        }
47    }
48}
49
50impl<A, const PAGE_SIZE: usize> Iterator for PageIter<PAGE_SIZE, A>
51where
52    A: MemoryAddr,
53{
54    type Item = A;
55
56    fn next(&mut self) -> Option<Self::Item> {
57        if self.start < self.end {
58            let ret = self.start;
59            self.start = self.start.add(PAGE_SIZE);
60            Some(ret)
61        } else {
62            None
63        }
64    }
65}