diff --git a/src/iter.rs b/src/iter.rs new file mode 100644 index 0000000..da310a1 --- /dev/null +++ b/src/iter.rs @@ -0,0 +1,60 @@ +use crate::{Address, 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, +{ + memory: &'a [u8], + regions: I, + base_address: Address, +} + +/// 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, +{ + /// Obtain an [`OverlapIterator`] over a subslice of `memory` that overlaps with the region in `self` + fn overlaps(self, memory: &'a [u8], base_address: Address) -> OverlapIterator; +} + +impl<'a, R, I> Iterator for OverlapIterator<'a, R, I> +where + R: Region, + I: Iterator, +{ + type Item = (&'a [u8], R, Address); + + fn next(&mut self) -> Option { + 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)) + .take_while(|index| region.contains(self.base_address + *index)); + 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)); + } + } + 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, +{ + fn overlaps(self, memory: &'a [u8], base_address: Address) -> OverlapIterator { + OverlapIterator { + memory, + regions: self, + base_address, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index f528d79..ff86488 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,25 +11,11 @@ #![deny(missing_docs)] #![deny(unsafe_code)] -use core::ops::{Add, BitOr, Sub}; +use core::ops::{Add, Sub}; use nb; -/// Trait to check if two entities are bitwise subset of another. -pub trait BitSubset { - /// Check that every '1' bit is a '1' on the right hand side. - fn is_subset_of(&self, rhs: &Self) -> bool; -} - -/// Blanket implementation of [`BitSubset`] for all arrays of a type implementing [`BitOr`] -impl> BitSubset for [T] { - fn is_subset_of(&self, rhs: &Self) -> bool { - if self.len() > rhs.len() { - false - } else { - self.iter().zip(rhs.iter()).all(|(a, b)| (*a | *b) == *b) - } - } -} +/// Currently contains [`OverlapIterator`] +pub mod iter; /// An address denotes the read/write address of a single word. #[derive(Default, Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] @@ -43,11 +29,26 @@ impl Add for Address { } } -impl Add
for Address { +impl Add for Address { + type Output = Self; + + fn add(self, rhs: isize) -> Self::Output { + Address((self.0 as isize + rhs) as u32) + } +} +impl Sub for Address { type Output = Self; - fn add(self, rhs: Address) -> Self::Output { - Address(self.0 + rhs.0) + fn sub(self, rhs: usize) -> Self::Output { + Address(self.0 - rhs as u32) + } +} + +impl Sub for Address { + type Output = Self; + + fn sub(self, rhs: isize) -> Self::Output { + Address((self.0 as isize - rhs) as u32) } } @@ -65,69 +66,6 @@ pub trait Region { fn contains(&self, address: Address) -> bool; } -/// Iterator producing block-region pairs, where each memory block maps to each -/// region. -pub struct OverlapIterator<'a, R, I> -where - R: Region, - I: Iterator, -{ - memory: &'a [u8], - regions: I, - base_address: Address, -} - -/// 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, -{ - /// Obtain an [`OverlapIterator`] over a subslice of `memory` that overlaps with the region in `self` - fn overlaps(self, memory: &'a [u8], base_address: Address) -> OverlapIterator; -} - -impl<'a, R, I> Iterator for OverlapIterator<'a, R, I> -where - R: Region, - I: Iterator, -{ - type Item = (&'a [u8], R, Address); - - fn next(&mut self) -> Option { - 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 + Address(*index as u32))) - .take_while(|index| region.contains(self.base_address + 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 + 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, -{ - fn overlaps(self, memory: &'a [u8], base_address: Address) -> OverlapIterator { - OverlapIterator { - memory, - regions: self, - base_address, - } - } -} - /// Storage trait pub trait ReadWrite { /// An enumeration of storage errors