1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use crate::Region;

/// Iterator producing block-region pairs, where each memory block maps to each
/// region.
pub struct OverlapIterator<'a, R, I>
where
	R: Region,
	I: Iterator<Item = R>,
{
	memory: &'a [u8],
	regions: I,
	base_address: u32,
}

/// Trait allowing us to automatically add an `overlaps` function to all iterators over [`Region`]
pub trait IterableByOverlaps<'a, R, I>
where
	R: Region,
	I: Iterator<Item = R>,
{
	/// Obtain an [`OverlapIterator`] over a subslice of `memory` that overlaps with the region in `self`
	fn overlaps(self, memory: &'a [u8], base_address: u32) -> OverlapIterator<R, I>;
}

impl<'a, R, I> Iterator for OverlapIterator<'a, R, I>
where
	R: Region,
	I: Iterator<Item = R>,
{
	type Item = (&'a [u8], R, u32);

	fn next(&mut self) -> Option<Self::Item> {
		while let Some(region) = self.regions.next() {
			//  TODO: This might be possible to do in a smarter way?
			let mut block_range = (0..self.memory.len())
				.skip_while(|index| !region.contains(self.base_address + *index as u32))
				.take_while(|index| region.contains(self.base_address + *index as u32));
			if let Some(start) = block_range.next() {
				let end = block_range.last().unwrap_or(start) + 1;
				return Some((
					&self.memory[start..end],
					region,
					self.base_address + start as u32,
				));
			}
		}
		None
	}
}

/// Blanket implementation for all types implementing [`Iterator`] over [`Regions`]
impl<'a, R, I> IterableByOverlaps<'a, R, I> for I
where
	R: Region,
	I: Iterator<Item = R>,
{
	fn overlaps(self, memory: &'a [u8], base_address: u32) -> OverlapIterator<R, I> {
		OverlapIterator {
			memory,
			regions: self,
			base_address,
		}
	}
}