diff --git a/Cargo.toml b/Cargo.toml index 4f3e857..58eec4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,3 @@ default = ["serde"] debug = 2 codegen-units = 1 lto = true - -[[bench]] -name = "bench" -harness = false diff --git a/src/impls/mirror.rs b/src/impls/mirror.rs index e240f3b..6c81584 100644 --- a/src/impls/mirror.rs +++ b/src/impls/mirror.rs @@ -16,7 +16,7 @@ impl Default for MirrorRegion { } } -impl Region for MirrorRegion { +impl> Region for MirrorRegion { type ReadItem<'a> = T where T: 'a; type Index = T; diff --git a/src/impls/slice.rs b/src/impls/slice.rs index 7d49ec2..03f08a6 100644 --- a/src/impls/slice.rs +++ b/src/impls/slice.rs @@ -9,19 +9,18 @@ use crate::{CopyOnto, Region, ReserveItems}; #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct SliceRegion { - // offsets: Vec, slices: Vec, inner: C, } impl Region for SliceRegion { - type ReadItem<'a> = (&'a C, &'a [C::Index]) where Self: 'a; + type ReadItem<'a> = ReadSlice<'a, C> where Self: 'a; type Index = (usize, usize); #[inline] fn index(&self, (start, end): Self::Index) -> Self::ReadItem<'_> { let slice = &self.slices[start..end]; - (&self.inner, slice) + ReadSlice(&self.inner, slice) } #[inline] @@ -37,7 +36,6 @@ impl Region for SliceRegion { #[inline] fn clear(&mut self) { - // self.offsets.clear(); self.slices.clear(); self.inner.clear(); } @@ -52,6 +50,58 @@ impl Default for SliceRegion { } } +/// A helper to read data out of a slice region. +#[derive(Debug)] +pub struct ReadSlice<'a, C: Region>(pub &'a C, pub &'a [C::Index]); + +impl<'a, C: Region> ReadSlice<'a, C> { + /// Read the n-th item from the underlying region. + #[inline] + pub fn get(&self, index: usize) -> C::ReadItem<'_> { + self.0.index(self.1[index]) + } + + /// The number in this slice. + pub fn len(&self) -> usize { + self.1.len() + } + + /// Test if this slice is empty. + pub fn is_empty(&self) -> bool { + self.1.is_empty() + } +} + +impl<'a, C: Region> Clone for ReadSlice<'a, C> { + #[inline] + fn clone(&self) -> Self { + Self(self.0, self.1) + } +} + +impl<'a, C: Region> Copy for ReadSlice<'a, C> {} + +impl<'a, C: Region> IntoIterator for ReadSlice<'a, C> { + type Item = C::ReadItem<'a>; + type IntoIter = ReadSliceIter<'a, C>; + + fn into_iter(self) -> Self::IntoIter { + ReadSliceIter(self.0, self.1.iter()) + } +} + +#[derive(Debug, Clone)] +pub struct ReadSliceIter<'a, C: Region>(&'a C, std::slice::Iter<'a, C::Index>); + +impl<'a, C: Region> Iterator for ReadSliceIter<'a, C> { + type Item = C::ReadItem<'a>; + + #[inline] + fn next(&mut self) -> Option { + self.1.next().map(|idx| self.0.index(*idx)) + } +} + impl<'a, C, T: 'a> CopyOnto> for &'a [T] where C: Region, @@ -136,13 +186,13 @@ where } } -impl<'a, C: Region + 'a> CopyOnto> for &'a (&'a C, &'a [C::Index]) +impl<'a, C: Region + 'a> CopyOnto> for ReadSlice<'a, C> where C::ReadItem<'a>: CopyOnto, { #[inline] fn copy_onto(self, target: &mut SliceRegion) -> as Region>::Index { - let (container, indexes) = self; + let ReadSlice(container, indexes) = self; let start = target.slices.len(); target.slices.extend( indexes @@ -158,10 +208,10 @@ where { target .slices - .reserve(items.clone().map(|(_c, is)| is.len()).sum()); + .reserve(items.clone().map(|ReadSlice(_c, is)| is.len()).sum()); CopyOnto::reserve_items( &mut target.inner, - items.flat_map(|(c, is)| is.iter().map(|i| c.index(*i))), + items.flat_map(|ReadSlice(c, is)| is.iter().map(|i| c.index(*i))), ) } } diff --git a/src/impls/string.rs b/src/impls/string.rs index 7cd2f64..6ec1bb5 100644 --- a/src/impls/string.rs +++ b/src/impls/string.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use crate::impls::slice_copy::CopyRegion; -use crate::{Containerized, CopyOnto, Region, ReserveItems, SliceRegion}; +use crate::{Containerized, CopyOnto, Region, ReserveItems}; /// A region to store strings and read `&str`. #[derive(Default, Debug, Clone)] @@ -13,7 +13,7 @@ pub struct StringRegion { impl Region for StringRegion { type ReadItem<'a> = &'a str where Self: 'a ; - type Index = > as Region>::Index; + type Index = as Region>::Index; #[inline] fn index(&self, index: Self::Index) -> Self::ReadItem<'_> { diff --git a/src/lib.rs b/src/lib.rs index 68fa830..884a6dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ impl Index for T {} /// A region to store data. pub trait Region: Default { /// The type of the data that one gets out of the container. - type ReadItem<'a> + type ReadItem<'a>: CopyOnto where Self: 'a; @@ -336,12 +336,15 @@ mod tests { #[test] fn all_types() { - fn test_copy(t: T) + fn test_copy(t: T) where T: CopyOnto, { let mut c = FlatStack::default(); c.copy(t); + + let mut cc = c.clone(); + cc.copy(c.get(0)); } test_copy::<_, StringRegion>(&"a".to_string()); @@ -413,4 +416,17 @@ mod tests { test_copy::<_, <(u8, u8) as Containerized>::Region>((1, 2)); } + + #[test] + fn slice_region_read_item() { + let mut c = FlatStack::>>::default(); + c.copy(vec![1, 2, 3]); + + let mut r = SliceRegion::>::default(); + let idx = [1, 2, 3].copy_onto(&mut r); + let read_item = r.index(idx); + let _read_item2 = read_item.clone(); + let _read_item3 = read_item; + assert_eq!(vec![1, 2, 3], read_item.into_iter().collect::>()); + } }