1use crate::error::{Error, Result};
2use std::ops::Range;
3
4pub fn after(
6 origin: *const (),
7 range: Option<Range<usize>>,
8) -> impl Iterator<Item = Result<*const ()>> {
9 FreeRegionIter::new(origin, range, SearchDirection::After)
10}
11
12pub fn before(
14 origin: *const (),
15 range: Option<Range<usize>>,
16) -> impl Iterator<Item = Result<*const ()>> {
17 FreeRegionIter::new(origin, range, SearchDirection::Before)
18}
19
20enum SearchDirection {
22 Before,
23 After,
24}
25
26struct FreeRegionIter {
28 range: Range<usize>,
29 search: SearchDirection,
30 current: usize,
31}
32
33impl FreeRegionIter {
34 fn new(origin: *const (), range: Option<Range<usize>>, search: SearchDirection) -> Self {
36 FreeRegionIter {
37 range: range.unwrap_or(0..usize::max_value()),
38 current: origin as usize,
39 search,
40 }
41 }
42}
43
44impl Iterator for FreeRegionIter {
45 type Item = Result<*const ()>;
46
47 fn next(&mut self) -> Option<Self::Item> {
49 let page_size = region::page::size();
50
51 while self.current > 0 && self.range.contains(&self.current) {
52 match region::query(self.current as *const usize) {
53 Ok(region) => {
54 let range = region.as_range();
55 self.current = match self.search {
56 SearchDirection::Before => range.start.saturating_sub(page_size),
57 SearchDirection::After => range.end,
58 }
59 },
60 Err(error) => {
61 let result = Some(match error {
63 region::Error::UnmappedRegion => Ok(self.current as *const _),
64 inner => Err(Error::RegionFailure(inner)),
65 });
66
67 self.current = match self.search {
69 SearchDirection::Before => self.current.saturating_sub(page_size),
70 SearchDirection::After => self.current + page_size,
71 };
72
73 return result;
74 },
75 }
76 }
77
78 None
79 }
80}