| 1 | use crate::Region; |
| 2 | |
| 3 | /// Iterator producing block-region pairs, where each memory block maps to each |
| 4 | /// region. |
| 5 | pub struct OverlapIterator<'a, R, I> |
| 6 | where |
| 7 | R: Region, |
| 8 | I: Iterator<Item = R>, |
| 9 | { |
| 10 | memory: &'a [u8], |
| 11 | regions: I, |
| 12 | base_address: u32, |
| 13 | } |
| 14 | |
| 15 | /// Trait allowing us to automatically add an `overlaps` function to all iterators over [`Region`] |
| 16 | pub trait IterableByOverlaps<'a, R, I> |
| 17 | where |
| 18 | R: Region, |
| 19 | I: Iterator<Item = R>, |
| 20 | { |
| 21 | /// Obtain an [`OverlapIterator`] over a subslice of `memory` that overlaps with the region in `self` |
| 22 | fn overlaps(self, memory: &'a [u8], base_address: u32) -> OverlapIterator<R, I>; |
| 23 | } |
| 24 | |
| 25 | impl<'a, R, I> Iterator for OverlapIterator<'a, R, I> |
| 26 | where |
| 27 | R: Region, |
| 28 | I: Iterator<Item = R>, |
| 29 | { |
| 30 | type Item = (&'a [u8], R, u32); |
| 31 | |
| 32 | fn next(&mut self) -> Option<Self::Item> { |
| 33 | while let Some(region: R) = self.regions.next() { |
| 34 | // TODO: This might be possible to do in a smarter way? |
| 35 | let mut block_range: impl Iterator = (0..self.memory.len()) |
| 36 | .skip_while(|index: &usize| !region.contains(self.base_address + *index as u32)) |
| 37 | .take_while(|index: &usize| region.contains(self.base_address + *index as u32)); |
| 38 | if let Some(start: usize) = block_range.next() { |
| 39 | let end: usize = block_range.last().unwrap_or(default:start) + 1; |
| 40 | return Some(( |
| 41 | &self.memory[start..end], |
| 42 | region, |
| 43 | self.base_address + start as u32, |
| 44 | )); |
| 45 | } |
| 46 | } |
| 47 | None |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | /// Blanket implementation for all types implementing [`Iterator`] over [`Regions`] |
| 52 | impl<'a, R, I> IterableByOverlaps<'a, R, I> for I |
| 53 | where |
| 54 | R: Region, |
| 55 | I: Iterator<Item = R>, |
| 56 | { |
| 57 | fn overlaps(self, memory: &'a [u8], base_address: u32) -> OverlapIterator<R, I> { |
| 58 | OverlapIterator { |
| 59 | memory, |
| 60 | regions: self, |
| 61 | base_address, |
| 62 | } |
| 63 | } |
| 64 | } |
| 65 | |