embedded_storage/
iter.rs

1use crate::Region;
2
3/// Iterator producing block-region pairs, where each memory block maps to each
4/// region.
5pub struct OverlapIterator<'a, R, I>
6where
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`]
16pub trait IterableByOverlaps<'a, R, I>
17where
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
25impl<'a, R, I> Iterator for OverlapIterator<'a, R, I>
26where
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) = self.regions.next() {
34			//  TODO: This might be possible to do in a smarter way?
35			let mut block_range = (0..self.memory.len())
36				.skip_while(|index| !region.contains(self.base_address + *index as u32))
37				.take_while(|index| region.contains(self.base_address + *index as u32));
38			if let Some(start) = block_range.next() {
39				let end = block_range.last().unwrap_or(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`]
52impl<'a, R, I> IterableByOverlaps<'a, R, I> for I
53where
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}