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}