From 44ff5b54702a2f5421939bd841bd8609b363f8cb Mon Sep 17 00:00:00 2001 From: Moritz Hoffmann Date: Fri, 8 Nov 2024 12:46:35 +0100 Subject: [PATCH] wip Signed-off-by: Moritz Hoffmann --- README.md | 10 +- benches/bench.rs | 3 +- src/impls.rs | 18 +- src/impls/slice.rs | 362 +++++++++++++++++++++------------------ src/impls/slice_owned.rs | 282 +++++++++++++++++------------- src/impls/string.rs | 92 +++++----- src/impls/tuple.rs | 89 +++++----- src/impls/vec.rs | 91 +++++++--- src/lib.rs | 162 ++++++++++-------- tests/cow.rs | 3 +- tests/person.rs | 3 +- tests/recursive.rs | 3 +- 12 files changed, 645 insertions(+), 473 deletions(-) diff --git a/README.md b/README.md index c49ca46..0f5dda5 100644 --- a/README.md +++ b/README.md @@ -5,18 +5,18 @@ A flat container for Rust. ```toml [dependencies] -flatcontainer = "0.4" +flatcontainer = "0.6" ``` ## Example ```rust -use flatcontainer::FlatStack; +use flatcontainer::{Index, RegionPreference}; let r: Result<_, u16> = Ok("abc"); -let mut c = FlatStack::default_impl::>(); -c.copy(&r); -assert_eq!(r, c.get(0)); +let mut c = < as RegionPreference>::Region>::default(); +c.push(&r); +assert_eq!(r, c.index(0)); ``` ## Details diff --git a/benches/bench.rs b/benches/bench.rs index ba8cf73..d951bff 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,5 +1,5 @@ //! A simple benchmark for flatcontainer, adopted from `columnation`'s benchmark. - +/* use codspeed_bencher_compat::{benchmark_group, benchmark_main, Bencher}; use flatcontainer::impls::deduplicate::{CollapseSequence, ConsecutiveIndexPairs}; use flatcontainer::impls::index::IndexOptimized; @@ -524,3 +524,4 @@ benchmark_group!( vec_u_vn_s_realloc, ); benchmark_main!(clone, copy, copy_flat, copy_region, alloc); +*/ diff --git a/src/impls.rs b/src/impls.rs index 3dbf004..93b43ac 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -1,16 +1,16 @@ //! Various region implementations. -pub mod codec; -pub mod columns; -pub mod deduplicate; -pub mod huffman_container; -pub mod index; -pub mod mirror; -pub mod option; -pub mod result; +// pub mod codec; +// pub mod columns; +// pub mod deduplicate; +// pub mod huffman_container; +// pub mod index; +// pub mod mirror; +// pub mod option; +// pub mod result; pub mod slice; pub mod slice_owned; -pub mod storage; +// pub mod storage; pub mod string; pub mod tuple; mod vec; diff --git a/src/impls/slice.rs b/src/impls/slice.rs index 34dda42..4780cb1 100644 --- a/src/impls/slice.rs +++ b/src/impls/slice.rs @@ -7,8 +7,10 @@ use std::ops::{Deref, Range}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::impls::index::IndexContainer; -use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems}; +use crate::{ + Clear, HeapSize, Index, IndexAs, IntoOwned, Len, Push, Region, RegionPreference, Reserve, + ReserveItems, +}; impl RegionPreference for Vec { type Owned = Vec; @@ -25,6 +27,8 @@ impl RegionPreference for [T; N] { type Region = SliceRegion; } +type Idx = u64; + /// A container representing slices of data. /// /// Reading from this region is more involved than for others, because the data only exists in @@ -36,7 +40,7 @@ impl RegionPreference for [T; N] { /// /// We fill some data into a slice region and use the [`ReadSlice`] to extract it later. /// ``` -/// use flatcontainer::{RegionPreference, Push, Region, SliceRegion}; +/// use flatcontainer::{RegionPreference, Push, Region, SliceRegion, Index}; /// let mut r = ::Region>>::default(); /// /// let panagram_en = "The quick fox jumps over the lazy dog" @@ -46,88 +50,123 @@ impl RegionPreference for [T; N] { /// .split(" ") /// .collect::>(); /// -/// let en_index = r.push(&panagram_en); -/// let de_index = r.push(&panagram_de); +/// r.push(&panagram_en); +/// r.push(&panagram_de); /// -/// assert!(panagram_de.into_iter().eq(r.index(de_index))); -/// assert!(panagram_en.into_iter().eq(r.index(en_index))); +/// assert!(panagram_de.into_iter().eq(r.index(0))); +/// assert!(panagram_en.into_iter().eq(r.index(1))); /// -/// assert_eq!(r.index(de_index).get(2), "jagen"); +/// assert_eq!(r.index(1).get(2), "jagen"); /// ``` #[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct SliceRegion::Index>> { - /// Container of slices. - slices: O, +pub struct SliceRegion> { + /// Container of bounds. + bounds: B, /// Inner region. inner: R, } impl Clone for SliceRegion where - R: Region + Clone, + R: Clone, O: Clone, { fn clone(&self) -> Self { Self { - slices: self.slices.clone(), + bounds: self.bounds.clone(), inner: self.inner.clone(), } } fn clone_from(&mut self, source: &Self) { - self.slices.clone_from(&source.slices); + self.bounds.clone_from(&source.bounds); self.inner.clone_from(&source.inner); } } -impl> Region for SliceRegion { - type Owned = Vec; - type ReadItem<'a> = ReadSlice<'a, R, O> where Self: 'a; - type Index = (usize, usize); - +impl Region for SliceRegion { #[inline] fn merge_regions<'a>(regions: impl Iterator + Clone) -> Self where Self: 'a, { Self { - slices: O::default(), + bounds: B::merge_regions(regions.clone().map(|r| &r.bounds)), inner: R::merge_regions(regions.map(|r| &r.inner)), } } - #[inline] - fn index(&self, (start, end): Self::Index) -> Self::ReadItem<'_> { - ReadSlice(Ok(ReadSliceInner { - region: self, - start, - end, - })) - } - #[inline] fn reserve_regions<'a, I>(&mut self, regions: I) where Self: 'a, I: Iterator + Clone, { - self.slices - .reserve(regions.clone().map(|r| r.slices.len()).sum()); + self.bounds + .reserve_regions(regions.clone().map(|r| &r.bounds)); self.inner.reserve_regions(regions.map(|r| &r.inner)); } +} +impl Len for SliceRegion +where + B: Len, +{ + #[inline] + fn len(&self) -> usize { + self.bounds.len() + } +} + +impl Clear for SliceRegion +where + R: Clear, + B: Clear, +{ #[inline] fn clear(&mut self) { - self.slices.clear(); + self.bounds.clear(); self.inner.clear(); } - +} +impl HeapSize for SliceRegion +where + R: HeapSize, + B: HeapSize, +{ #[inline] fn heap_size(&self, mut callback: F) { - self.slices.heap_size(&mut callback); + self.bounds.heap_size(&mut callback); self.inner.heap_size(callback); } +} + +impl Index for SliceRegion +where + R: Index, + B: IndexAs, +{ + type Owned = Vec; + + type ReadItem<'a> = ReadSlice<'a, R, B> where Self: 'a; + #[inline] + fn index(&self, index: usize) -> Self::ReadItem<'_> { + let start = if index == 0 { + 0 + } else { + self.bounds + .index_as(index - 1) + .try_into() + .expect("must fit") + }; + let end = self.bounds.index_as(index).try_into().expect("must fit"); + ReadSlice(Ok(ReadSliceInner { + region: self, + start, + end, + })) + } #[inline] fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b> @@ -138,22 +177,20 @@ impl> Region for SliceRegion { } } -impl> Default for SliceRegion { +impl Default for SliceRegion { #[inline] fn default() -> Self { Self { - slices: O::default(), + bounds: B::default(), inner: R::default(), } } } /// A helper to read data out of a slice region. -pub struct ReadSlice<'a, R: Region, O: IndexContainer = Vec<::Index>>( - Result, &'a [R::Owned]>, -); +pub struct ReadSlice<'a, R: Index, B>(Result, &'a [R::Owned]>); -impl> ReadSlice<'_, R, O> { +impl> ReadSlice<'_, R, B> { /// Read the n-th item from the underlying region. /// /// # Panics @@ -194,7 +231,7 @@ impl> ReadSlice<'_, R, O> { } } -impl> PartialEq for ReadSlice<'_, R, O> +impl> PartialEq for ReadSlice<'_, R, B> where for<'a> R::ReadItem<'a>: PartialEq, { @@ -203,12 +240,9 @@ where } } -impl> Eq for ReadSlice<'_, R, O> where - for<'a> R::ReadItem<'a>: Eq -{ -} +impl> Eq for ReadSlice<'_, R, B> where for<'a> R::ReadItem<'a>: Eq {} -impl> PartialOrd for ReadSlice<'_, R, O> +impl> PartialOrd for ReadSlice<'_, R, O> where for<'a> R::ReadItem<'a>: PartialOrd, { @@ -217,7 +251,7 @@ where } } -impl> Ord for ReadSlice<'_, R, O> +impl> Ord for ReadSlice<'_, R, O> where for<'a> R::ReadItem<'a>: Ord, { @@ -226,13 +260,13 @@ where } } -struct ReadSliceInner<'a, R: Region, O: IndexContainer = Vec<::Index>> { +struct ReadSliceInner<'a, R, O> { region: &'a SliceRegion, start: usize, end: usize, } -impl> ReadSliceInner<'_, R, O> { +impl> ReadSliceInner<'_, R, O> { /// Read the n-th item from the underlying region. /// /// # Panics @@ -249,9 +283,7 @@ impl> ReadSliceInner<'_, R, O> { self.start, self.end ); - self.region - .inner - .index(self.region.slices.index(self.start + index)) + self.region.inner.index(self.start + index) } /// The number of elements in this slice. @@ -267,7 +299,7 @@ impl> ReadSliceInner<'_, R, O> { } } -impl> Debug for ReadSlice<'_, R, O> +impl> Debug for ReadSlice<'_, R, O> where for<'a> R::ReadItem<'a>: Debug, { @@ -276,27 +308,27 @@ where } } -impl> Clone for ReadSlice<'_, R, O> { +impl> Clone for ReadSlice<'_, R, O> { #[inline] fn clone(&self) -> Self { *self } } -impl> Clone for ReadSliceInner<'_, R, O> { +impl> Clone for ReadSliceInner<'_, R, O> { #[inline] fn clone(&self) -> Self { *self } } -impl> Copy for ReadSlice<'_, R, O> {} -impl> Copy for ReadSliceInner<'_, R, O> {} +impl> Copy for ReadSlice<'_, R, O> {} +impl> Copy for ReadSliceInner<'_, R, O> {} impl<'a, R, O> IntoOwned<'a> for ReadSlice<'a, R, O> where - R: Region, - O: IndexContainer, + R: Index, + O: IndexAs, { type Owned = Vec; @@ -321,7 +353,7 @@ where } } -impl<'a, R: Region, O: IndexContainer> IntoIterator for ReadSlice<'a, R, O> { +impl<'a, R: Index, O: IndexAs> IntoIterator for ReadSlice<'a, R, O> { type Item = R::ReadItem<'a>; type IntoIter = ReadSliceIter<'a, R, O>; @@ -338,11 +370,11 @@ impl<'a, R: Region, O: IndexContainer> IntoIterator for ReadSlice<'a, /// An iterator over the items read from a slice region. #[derive(Debug)] -pub struct ReadSliceIter<'a, C: Region, O: IndexContainer>( +pub struct ReadSliceIter<'a, C: Index, O: IndexAs>( Result, std::slice::Iter<'a, C::Owned>>, ); -impl<'a, C: Region, O: IndexContainer> Clone for ReadSliceIter<'a, C, O> { +impl<'a, C: Index, O: IndexAs> Clone for ReadSliceIter<'a, C, O> { #[inline] fn clone(&self) -> Self { Self(self.0.clone()) @@ -351,19 +383,16 @@ impl<'a, C: Region, O: IndexContainer> Clone for ReadSliceIter<'a, C, /// An iterator over the items read from a slice region. #[derive(Debug)] -pub struct ReadSliceIterInner<'a, C: Region, O: IndexContainer>( - &'a SliceRegion, - Range, -); +pub struct ReadSliceIterInner<'a, C: Index, O: IndexAs>(&'a SliceRegion, Range); -impl<'a, C: Region, O: IndexContainer> Clone for ReadSliceIterInner<'a, C, O> { +impl<'a, C: Index, O: IndexAs> Clone for ReadSliceIterInner<'a, C, O> { #[inline] fn clone(&self) -> Self { Self(self.0, self.1.clone()) } } -impl<'a, C: Region, O: IndexContainer> Iterator for ReadSliceIter<'a, C, O> { +impl<'a, C: Index, O: IndexAs> Iterator for ReadSliceIter<'a, C, O> { type Item = C::ReadItem<'a>; #[inline] @@ -377,100 +406,101 @@ impl<'a, C: Region, O: IndexContainer> Iterator for ReadSliceIter<'a, impl<'a, R, O> ExactSizeIterator for ReadSliceIter<'a, R, O> where - R: Region, - O: IndexContainer, + R: Index, + O: IndexAs, std::slice::Iter<'a, R::Owned>: ExactSizeIterator, ReadSliceIterInner<'a, R, O>: ExactSizeIterator, { } -impl<'a, C: Region, O: IndexContainer> Iterator for ReadSliceIterInner<'a, C, O> { +impl<'a, C: Index, O: IndexAs> Iterator for ReadSliceIterInner<'a, C, O> { type Item = C::ReadItem<'a>; #[inline] fn next(&mut self) -> Option { - self.1 - .next() - .map(|idx| self.0.inner.index(self.0.slices.index(idx))) + self.1.next().map(|idx| self.0.inner.index(idx)) } } impl<'a, R, O> ExactSizeIterator for ReadSliceIterInner<'a, R, O> where - R: Region, - O: IndexContainer, + R: Index, + O: IndexAs, Range: ExactSizeIterator, { } -impl<'a, C, T, O> Push<&'a [T]> for SliceRegion +impl<'a, C, T, B> Push<&'a [T]> for SliceRegion where - C: Region + Push<&'a T>, - O: IndexContainer, + C: Push<&'a T> + Len, + B: IndexAs + Push, { #[inline] - fn push(&mut self, item: &'a [T]) -> as Region>::Index { - let start = self.slices.len(); - self.slices.extend(item.iter().map(|t| self.inner.push(t))); - (start, self.slices.len()) + fn push(&mut self, items: &'a [T]) { + for item in items.iter() { + self.inner.push(item); + } + self.bounds + .push(self.inner.len().try_into().expect("must fit")); } } impl<'a, T, R, O> ReserveItems<&'a [T]> for SliceRegion where - R: Region + ReserveItems<&'a T>, - O: IndexContainer, + R: ReserveItems<&'a T>, + O: Reserve, { #[inline] fn reserve_items(&mut self, items: I) where I: Iterator + Clone, { - self.slices.reserve(items.clone().map(<[T]>::len).sum()); + self.bounds.reserve(1); self.inner.reserve_items(items.flatten()); } } impl Push> for SliceRegion where - C: Region + Push, - O: IndexContainer, + C: Push + Len, + O: IndexAs + Push, { #[inline] - fn push(&mut self, item: Vec) -> as Region>::Index { - let start = self.slices.len(); - self.slices - .extend(item.into_iter().map(|t| self.inner.push(t))); - (start, self.slices.len()) + fn push(&mut self, items: Vec) { + for item in items { + self.inner.push(item); + } + self.bounds + .push(self.inner.len().try_into().expect("must fit")); } } impl Push<&Vec> for SliceRegion where - for<'a> C: Region + Push<&'a T>, - O: IndexContainer, + C: for<'a> Push<&'a T> + Len, + O: Push + IndexAs, { #[inline] - fn push(&mut self, item: &Vec) -> as Region>::Index { + fn push(&mut self, item: &Vec) { self.push(item.as_slice()) } } impl<'a, C, T, O> Push<&&'a Vec> for SliceRegion where - C: Region + Push<&'a T>, - O: IndexContainer, + C: Push<&'a T> + Len, + O: Push + IndexAs, { #[inline] - fn push(&mut self, item: &&'a Vec) -> as Region>::Index { + fn push(&mut self, item: &&'a Vec) { self.push(item.as_slice()) } } impl<'a, T, R, O> ReserveItems<&'a Vec> for SliceRegion where - for<'b> R: Region + ReserveItems<&'b T>, - O: IndexContainer, + R: ReserveItems<&'a T>, + O: Reserve, { #[inline] fn reserve_items(&mut self, items: I) @@ -481,22 +511,21 @@ where } } -impl<'a, C, O> Push> for SliceRegion +impl<'a, C, B> Push> for SliceRegion where - C: Region + Push<::ReadItem<'a>>, - O: IndexContainer, + C: Index + Push<::ReadItem<'a>> + Len, + B: IndexAs + Push, { #[inline] - fn push(&mut self, item: ReadSlice<'a, C, O>) -> as Region>::Index { + fn push(&mut self, item: ReadSlice<'a, C, B>) { match item.0 { Ok(inner) => self.push(inner), Err(slice) => { - let start_len = self.slices.len(); for item in slice.iter().map(IntoOwned::borrow_as) { - let index = self.inner.push(item); - self.slices.push(index); + self.inner.push(item); } - (start_len, self.slices.len()) + self.bounds + .push(self.inner.len().try_into().expect("must fit")); } } } @@ -504,59 +533,61 @@ where impl<'a, C, O> Push> for SliceRegion where - C: Region + Push<::ReadItem<'a>>, - O: IndexContainer, + C: Index + Push<::ReadItem<'a>> + Len, + O: IndexAs + Push, { #[inline] - fn push(&mut self, item: ReadSliceInner<'a, C, O>) -> as Region>::Index { + fn push(&mut self, item: ReadSliceInner<'a, C, O>) { let ReadSliceInner { region, start, end } = item; - let start_len = self.slices.len(); for index in start..end { - let index = region.slices.index(index); - let index = self.inner.push(region.inner.index(index)); - self.slices.push(index); + self.inner.push(region.inner.index(index)); } - (start_len, self.slices.len()) + self.bounds + .push(self.inner.len().try_into().expect("must fit")); } } impl Push<[T; N]> for SliceRegion where - for<'a> R: Region + Push<&'a T>, - O: IndexContainer, + for<'a> R: Push + Len, + O: IndexAs + Push, { #[inline] - fn push(&mut self, item: [T; N]) -> as Region>::Index { - self.push(item.as_slice()) + fn push(&mut self, items: [T; N]) { + for item in items { + self.inner.push(item); + } + self.bounds + .push(self.inner.len().try_into().expect("must fit")); } } impl<'a, T, R, O, const N: usize> Push<&'a [T; N]> for SliceRegion where - R: Region + Push<&'a T>, - O: IndexContainer, + R: Push<&'a T> + Len, + O: Push + IndexAs, { #[inline] - fn push(&mut self, item: &'a [T; N]) -> as Region>::Index { + fn push(&mut self, item: &'a [T; N]) { self.push(item.as_slice()) } } impl<'a, T, R, O, const N: usize> Push<&&'a [T; N]> for SliceRegion where - R: Region + Push<&'a T>, - O: IndexContainer, + R: Push<&'a T> + Len, + O: Push + IndexAs, { #[inline] - fn push(&mut self, item: &&'a [T; N]) -> as Region>::Index { + fn push(&mut self, item: &&'a [T; N]) { self.push(item.as_slice()) } } impl<'a, T, R, O, const N: usize> ReserveItems<&'a [T; N]> for SliceRegion where - R: Region + ReserveItems<&'a T>, - O: IndexContainer, + R: ReserveItems<&'a T>, + O: Reserve, { fn reserve_items(&mut self, items: I) where @@ -568,15 +599,14 @@ where impl<'a, R, O> ReserveItems> for SliceRegion where - R: Region + ReserveItems<::ReadItem<'a>> + 'a, - O: IndexContainer, + R: Index + ReserveItems<::ReadItem<'a>> + 'a, + O: Reserve + IndexAs, { fn reserve_items(&mut self, items: I) where I: Iterator> + Clone, { - self.slices - .reserve(items.clone().map(|read_slice| read_slice.len()).sum()); + self.bounds.reserve(1); self.inner.reserve_items(items.flatten()); } } @@ -584,19 +614,19 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{MirrorRegion, Push, Region}; + use crate::{Index, Push}; #[test] fn read_slice() { let s = [1, 2, 3, 4]; - let mut r = >>::default(); + let mut r = >>::default(); - let index = r.push(s); + r.push(s); - assert!(s.iter().copied().eq(r.index(index).iter())); + assert!(s.iter().eq(r.index(0).iter())); - let index = r.push(s); - let slice = r.index(index); + r.push(s); + let slice = r.index(1); assert_eq!(s.len(), slice.len()); assert!(!slice.is_empty()); assert_eq!(s.get(0), Some(&1)); @@ -604,8 +634,8 @@ mod tests { assert_eq!(s.get(2), Some(&3)); assert_eq!(s.get(3), Some(&4)); - let index = <_ as Push<[u8; 0]>>::push(&mut r, []); - let slice = r.index(index); + <_ as Push<[u8; 0]>>::push(&mut r, []); + let slice = r.index(2); assert_eq!(0, slice.len()); assert!(slice.is_empty()); } @@ -613,83 +643,83 @@ mod tests { #[test] #[should_panic] fn test_get_out_of_bounds() { - let mut r = >>::default(); - let index = r.push([1; 4]); + let mut r = >>::default(); + r.push([1; 4]); // Index 4 is out of bounds and expected to panic. - let _ = r.index(index).get(4); + let _ = r.index(0).get(4); } #[test] fn test_read_slice_debug() { - let mut r = >>::default(); - let index = r.push([1; 4]); + let mut r = >>::default(); + r.push([1; 4]); - assert_eq!("[1, 1, 1, 1]", format!("{:?}", r.index(index))); + assert_eq!("[1, 1, 1, 1]", format!("{:?}", r.index(0))); } #[test] fn test_read_slice_clone() { - let mut r = >>::default(); - let index = r.push([1; 4]); + let mut r = >>::default(); + r.push([1; 4]); - assert_eq!("[1, 1, 1, 1]", format!("{:?}", r.index(index).clone())); + assert_eq!("[1, 1, 1, 1]", format!("{:?}", r.index(0).clone())); } #[test] fn test_read_slice_eq() { - let mut r = >>::default(); - let index = r.push([1; 4]); + let mut r = >>::default(); + r.push([1; 4]); assert_eq!( as IntoOwned>::borrow_as(&vec![1; 4]), - r.index(index) + r.index(0) ); assert_ne!( as IntoOwned>::borrow_as(&vec![0; 4]), - r.index(index) + r.index(0) ); assert_ne!( as IntoOwned>::borrow_as(&vec![1; 5]), - r.index(index) + r.index(0) ); } #[test] fn test_read_slice_cmp() { - let mut r = >>::default(); - let index = r.push([1; 4]); + let mut r = >>::default(); + r.push([1; 4]); assert_eq!( Ordering::Less, - as IntoOwned>::borrow_as(&vec![0; 4]).cmp(&r.index(index)) + as IntoOwned>::borrow_as(&vec![0; 4]).cmp(&r.index(0)) ); assert_eq!( Ordering::Equal, - as IntoOwned>::borrow_as(&vec![1; 4]).cmp(&r.index(index)) + as IntoOwned>::borrow_as(&vec![1; 4]).cmp(&r.index(0)) ); assert_eq!( Ordering::Greater, - as IntoOwned>::borrow_as(&vec![2; 4]).cmp(&r.index(index)) + as IntoOwned>::borrow_as(&vec![2; 4]).cmp(&r.index(0)) ); assert_eq!( Ordering::Less, - as IntoOwned>::borrow_as(&vec![1; 3]).cmp(&r.index(index)) + as IntoOwned>::borrow_as(&vec![1; 3]).cmp(&r.index(0)) ); assert_eq!( Ordering::Equal, - as IntoOwned>::borrow_as(&vec![1; 4]).cmp(&r.index(index)) + as IntoOwned>::borrow_as(&vec![1; 4]).cmp(&r.index(0)) ); assert_eq!( Ordering::Greater, - as IntoOwned>::borrow_as(&vec![1; 5]).cmp(&r.index(index)) + as IntoOwned>::borrow_as(&vec![1; 5]).cmp(&r.index(0)) ); } #[test] fn test_reserve_ref_slice() { - let mut r = >>::default(); + let mut r = >>::default(); r.reserve_items(std::iter::once([1; 4].as_slice())); let mut cap = 0; r.heap_size(|_, ca| { @@ -700,7 +730,7 @@ mod tests { #[test] fn test_reserve_ref_vec() { - let mut r = >>::default(); + let mut r = >>::default(); r.reserve_items(std::iter::once(&vec![1; 4])); let mut cap = 0; r.heap_size(|_, ca| { @@ -711,7 +741,7 @@ mod tests { #[test] fn test_reserve_ref_array() { - let mut r = >>::default(); + let mut r = >>::default(); r.reserve_items(std::iter::once(&[1; 4])); let mut cap = 0; r.heap_size(|_, ca| { diff --git a/src/impls/slice_owned.rs b/src/impls/slice_owned.rs index 209e0e0..3e34f60 100644 --- a/src/impls/slice_owned.rs +++ b/src/impls/slice_owned.rs @@ -5,8 +5,10 @@ use std::marker::PhantomData; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::impls::storage::{PushStorage, Storage}; -use crate::{Push, PushIter, Region, ReserveItems}; +// use crate::impls::storage::{PushStorage, Storage}; +use crate::{Clear, HeapSize, Index, IndexAs, Len, Push, PushIter, Region, Reserve, ReserveItems}; + +type Idx = u64; /// A container for owned types. /// @@ -18,80 +20,142 @@ use crate::{Push, PushIter, Region, ReserveItems}; /// # Examples /// /// ``` -/// use flatcontainer::{Push, OwnedRegion, Region}; +/// use flatcontainer::{Push, OwnedRegion, Region, Index}; /// let mut r = >::default(); /// /// let panagram_en = "The quick fox jumps over the lazy dog"; /// let panagram_de = "Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich"; /// -/// let en_index = r.push(panagram_en.as_bytes()); -/// let de_index = r.push(panagram_de.as_bytes()); +/// r.push(panagram_en.as_bytes()); +/// r.push(panagram_de.as_bytes()); /// -/// assert_eq!(panagram_de.as_bytes(), r.index(de_index)); -/// assert_eq!(panagram_en.as_bytes(), r.index(en_index)); +/// assert_eq!(panagram_en.as_bytes(), r.index(0)); +/// assert_eq!(panagram_de.as_bytes(), r.index(1)); /// ``` #[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct OwnedRegion> { +pub struct OwnedRegion, B = Vec> { slices: S, + bounds: B, _marker: PhantomData, } -impl Clone for OwnedRegion { +impl Clone for OwnedRegion { fn clone(&self) -> Self { Self { slices: self.slices.clone(), + bounds: self.bounds.clone(), _marker: PhantomData, } } fn clone_from(&mut self, source: &Self) { self.slices.clone_from(&source.slices); + self.bounds.clone_from(&source.bounds); } } -impl Region for OwnedRegion +impl Region for OwnedRegion where [T]: ToOwned, - S: Storage + std::ops::Index, Output = [T]>, + S: Region + std::ops::Index, Output = [T]>, + B: Region, { - type Owned = <[T] as ToOwned>::Owned; - type ReadItem<'a> = &'a [T] where Self: 'a; - type Index = (usize, usize); - #[inline] fn merge_regions<'a>(regions: impl Iterator + Clone) -> Self where Self: 'a, { Self { - slices: S::merge_regions(regions.map(|r| &r.slices)), + slices: S::merge_regions(regions.clone().map(|r| &r.slices)), + bounds: B::merge_regions(regions.map(|r| &r.bounds)), _marker: PhantomData, } } - #[inline] - fn index(&self, (start, end): Self::Index) -> Self::ReadItem<'_> { - &self.slices[start..end] - } - #[inline] fn reserve_regions<'a, I>(&mut self, regions: I) where Self: 'a, I: Iterator + Clone, { - self.slices.reserve_regions(regions.map(|r| &r.slices)); + self.slices + .reserve_regions(regions.clone().map(|r| &r.slices)); + self.bounds.reserve_regions(regions.map(|r| &r.bounds)); + } +} + +impl Default for OwnedRegion { + #[inline] + fn default() -> Self { + Self { + slices: S::default(), + bounds: B::default(), + _marker: PhantomData, + } } +} +impl HeapSize for OwnedRegion +where + S: HeapSize, + B: HeapSize, +{ + #[inline] + fn heap_size(&self, mut callback: F) { + self.slices.heap_size(&mut callback); + self.bounds.heap_size(&mut callback); + } +} + +impl Clear for OwnedRegion +where + S: Clear, + B: Clear, +{ #[inline] fn clear(&mut self) { self.slices.clear(); + self.bounds.clear(); } +} +impl Len for OwnedRegion +where + B: Len, +{ #[inline] - fn heap_size(&self, callback: F) { - self.slices.heap_size(callback); + fn len(&self) -> usize { + self.bounds.len() + } + + #[inline] + fn is_empty(&self) -> bool { + self.bounds.is_empty() + } +} + +impl Index for OwnedRegion +where + [T]: ToOwned, + S: std::ops::Index, Output = [T]>, + B: IndexAs, +{ + type Owned = <[T] as ToOwned>::Owned; + type ReadItem<'a> = &'a [T] where Self: 'a; + + #[inline] + fn index(&self, index: usize) -> Self::ReadItem<'_> { + let start = if index == 0 { + 0 + } else { + self.bounds + .index_as(index - 1) + .try_into() + .expect("must fit") + }; + let end = self.bounds.index_as(index).try_into().expect("must fit"); + &self.slices[start..end] } #[inline] @@ -103,61 +167,46 @@ where } } -impl> Default for OwnedRegion { - #[inline] - fn default() -> Self { - Self { - slices: S::default(), - _marker: PhantomData, - } - } -} - -impl Push<[T; N]> for OwnedRegion +impl Push<[T; N]> for OwnedRegion where - [T]: ToOwned, - S: Storage - + for<'a> PushStorage> - + std::ops::Index, Output = [T]>, + S: Push + Len, + B: Push, { #[inline] - fn push(&mut self, item: [T; N]) -> as Region>::Index { - let start = self.slices.len(); - self.slices.push_storage(PushIter(item)); - (start, self.slices.len()) + fn push(&mut self, items: [T; N]) { + for item in items { + self.slices.push(item); + } + self.bounds + .push(self.slices.len().try_into().expect("must fit")); } } -impl Push<&[T; N]> for OwnedRegion +impl Push<&[T; N]> for OwnedRegion where - T: Clone, - S: Storage - + for<'a> PushStorage<&'a [T]> - + std::ops::Index, Output = [T]>, + OwnedRegion: for<'a> Push<&'a [T]>, { #[inline] - fn push(&mut self, item: &[T; N]) -> as Region>::Index { + fn push(&mut self, item: &[T; N]) { self.push(item.as_slice()) } } -impl Push<&&[T; N]> for OwnedRegion +impl Push<&&[T; N]> for OwnedRegion where - T: Clone, - S: Storage - + for<'a> PushStorage<&'a [T]> - + std::ops::Index, Output = [T]>, + Self: for<'a> Push<&'a [T]>, { #[inline] - fn push(&mut self, item: &&[T; N]) -> as Region>::Index { + fn push(&mut self, item: &&[T; N]) { self.push(*item) } } -impl<'b, T, S, const N: usize> ReserveItems<&'b [T; N]> for OwnedRegion +impl<'b, T, S, B, const N: usize> ReserveItems<&'b [T; N]> for OwnedRegion where T: Clone, - S: Storage + std::ops::Index, Output = [T]>, + S: Reserve, + B: Reserve, { #[inline] fn reserve_items(&mut self, items: I) @@ -168,35 +217,37 @@ where } } -impl Push<&[T]> for OwnedRegion +impl Push<&[T]> for OwnedRegion where T: Clone, - S: Storage - + for<'a> PushStorage<&'a [T]> - + std::ops::Index, Output = [T]>, + S: for<'a> Push<&'a T> + Len, + B: Push, { #[inline] - fn push(&mut self, item: &[T]) -> as Region>::Index { - let start = self.slices.len(); - self.slices.push_storage(item); - (start, self.slices.len()) + fn push(&mut self, items: &[T]) { + for item in items { + self.slices.push(item); + } + self.bounds + .push(self.slices.len().try_into().expect("must fit")); } } -impl> Push<&&[T]> for OwnedRegion +impl Push<&&[T]> for OwnedRegion where + T: Clone, for<'a> Self: Push<&'a [T]>, { #[inline] - fn push(&mut self, item: &&[T]) -> as Region>::Index { + fn push(&mut self, item: &&[T]) { self.push(*item) } } -impl<'b, T, S> ReserveItems<&'b [T]> for OwnedRegion +impl<'b, T, S, B> ReserveItems<&'b [T]> for OwnedRegion where - [T]: ToOwned, - S: Storage + std::ops::Index, Output = [T]>, + S: Reserve, + B: Reserve, { #[inline] fn reserve_items(&mut self, items: I) @@ -204,41 +255,38 @@ where I: Iterator + Clone, { self.slices.reserve(items.map(<[T]>::len).sum()); + self.bounds.reserve(1); } } -impl Push> for OwnedRegion +impl Push> for OwnedRegion where - [T]: ToOwned, - S: Storage - + for<'a> PushStorage<&'a mut Vec> - + std::ops::Index, Output = [T]>, + S: Push + Len, + B: Push, { #[inline] - fn push(&mut self, mut item: Vec) -> as Region>::Index { - let start = self.slices.len(); - self.slices.push_storage(&mut item); - (start, self.slices.len()) + fn push(&mut self, items: Vec) { + for item in items { + self.slices.push(item); + } + self.bounds + .push(self.slices.len().try_into().expect("must fit")); } } -impl Push<&Vec> for OwnedRegion +impl Push<&Vec> for OwnedRegion where - T: Clone, - S: Storage - + for<'a> PushStorage<&'a [T]> - + std::ops::Index, Output = [T]>, + Self: for<'a> Push<&'a [T]>, { #[inline] - fn push(&mut self, item: &Vec) -> as Region>::Index { + fn push(&mut self, item: &Vec) { self.push(item.as_slice()) } } -impl<'a, T, S> ReserveItems<&'a Vec> for OwnedRegion +impl<'a, T, S, B> ReserveItems<&'a Vec> for OwnedRegion where - [T]: ToOwned, - S: Storage + std::ops::Index, Output = [T]>, + Self: ReserveItems<&'a [T]>, { #[inline] fn reserve_items(&mut self, items: I) @@ -249,28 +297,26 @@ where } } -impl Push> for OwnedRegion +impl Push> for OwnedRegion where - I: IntoIterator, - ::IntoIter: ExactSizeIterator, - T: Clone, - S: Storage - + PushStorage> - + std::ops::Index, Output = [T]>, + I: IntoIterator, + S: Push + Len, + B: Push, { #[inline] - fn push(&mut self, item: PushIter) -> as Region>::Index { - let start = self.slices.len(); - self.slices.push_storage(item); - (start, self.slices.len()) + fn push(&mut self, items: PushIter) { + for item in items { + self.slices.push(item); + } + self.bounds + .push(self.slices.len().try_into().expect("must fit")); } } -impl ReserveItems> for OwnedRegion +impl ReserveItems> for OwnedRegion where - [T]: ToOwned, - S: Storage + std::ops::Index, Output = [T]>, - J: IntoIterator, + S: Reserve, + J: IntoIterator, { #[inline] fn reserve_items(&mut self, items: I) @@ -278,13 +324,13 @@ where I: Iterator> + Clone, { self.slices - .reserve(items.flat_map(|i| i.0.into_iter()).count()); + .reserve(items.flat_map(|i| i.into_iter()).count()); } } #[cfg(test)] mod tests { - use crate::{Push, PushIter, Region, ReserveItems}; + use crate::{Push, PushIter, ReserveItems}; use super::*; @@ -292,26 +338,31 @@ mod tests { fn test_copy_array() { let mut r = >::default(); r.reserve_items(std::iter::once(&[1; 4])); - let index = r.push([1; 4]); - assert_eq!([1, 1, 1, 1], r.index(index)); + assert_eq!(0, r.len()); + r.push([1; 4]); + assert_eq!([1, 1, 1, 1], r.index(0)); + assert_eq!(1, r.len()); } #[test] fn test_copy_ref_ref_array() { let mut r = >::default(); ReserveItems::reserve_items(&mut r, std::iter::once(&[1; 4])); - let index = r.push(&&[1; 4]); - assert_eq!([1, 1, 1, 1], r.index(index)); + r.push(&&[1; 4]); + assert_eq!([1, 1, 1, 1], r.index(0)); + assert_eq!(1, r.len()); } #[test] fn test_copy_vec() { let mut r = >::default(); ReserveItems::reserve_items(&mut r, std::iter::once(&vec![1; 4])); - let index = r.push(&vec![1; 4]); - assert_eq!([1, 1, 1, 1], r.index(index)); - let index = r.push(vec![2; 4]); - assert_eq!([2, 2, 2, 2], r.index(index)); + r.push(&vec![1; 4]); + assert_eq!([1, 1, 1, 1], r.index(0)); + assert_eq!(1, r.len()); + r.push(vec![2; 4]); + assert_eq!([2, 2, 2, 2], r.index(1)); + assert_eq!(2, r.len()); } #[test] @@ -319,7 +370,8 @@ mod tests { let mut r = >::default(); let iter = [1; 4].into_iter(); r.reserve_items(std::iter::once(PushIter(iter.clone()))); - let index = r.push(PushIter(iter)); - assert_eq!([1, 1, 1, 1], r.index(index)); + r.push(PushIter(iter)); + assert_eq!([1, 1, 1, 1], r.index(0)); + assert_eq!(1, r.len()); } } diff --git a/src/impls/string.rs b/src/impls/string.rs index e92e5bd..901ea55 100644 --- a/src/impls/string.rs +++ b/src/impls/string.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use crate::impls::slice_owned::OwnedRegion; -use crate::{Push, Region, RegionPreference, ReserveItems}; +use crate::{Clear, HeapSize, Index, Len, Push, Region, RegionPreference, ReserveItems}; /// A region to store strings and read `&str`. /// @@ -18,7 +18,7 @@ use crate::{Push, Region, RegionPreference, ReserveItems}; /// /// We fill some data into a string region and use extract it later. /// ``` -/// use flatcontainer::{RegionPreference, Push, OwnedRegion, Region, StringRegion}; +/// use flatcontainer::{RegionPreference, Push, OwnedRegion, Region, StringRegion, Index}; /// let mut r = ::default(); /// /// let panagram_en = "The quick fox jumps over the lazy dog"; @@ -27,8 +27,8 @@ use crate::{Push, Region, RegionPreference, ReserveItems}; /// let en_index = r.push(panagram_en); /// let de_index = r.push(panagram_de); /// -/// assert_eq!(panagram_de, r.index(de_index)); -/// assert_eq!(panagram_en, r.index(en_index)); +/// assert_eq!(panagram_en, r.index(0)); +/// assert_eq!(panagram_de, r.index(1)); /// ``` #[derive(Default, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -50,12 +50,8 @@ impl Clone for StringRegion { impl Region for StringRegion where - for<'a> R: Region = &'a [u8]> + 'a, + R: Region, { - type Owned = String; - type ReadItem<'a> = &'a str where Self: 'a ; - type Index = R::Index; - #[inline] fn merge_regions<'a>(regions: impl Iterator + Clone) -> Self where @@ -66,12 +62,6 @@ where } } - #[inline] - fn index(&self, index: Self::Index) -> Self::ReadItem<'_> { - // SAFETY: All Push implementations only accept correct utf8 data - unsafe { std::str::from_utf8_unchecked(self.inner.index(index)) } - } - #[inline] fn reserve_regions<'a, I>(&mut self, regions: I) where @@ -80,15 +70,19 @@ where { self.inner.reserve_regions(regions.map(|r| &r.inner)); } +} - #[inline] - fn clear(&mut self) { - self.inner.clear(); - } +impl Index for StringRegion +where + for<'a> R: Index = &'a [u8]> + 'a, +{ + type Owned = String; + type ReadItem<'a> = &'a str where Self: 'a ; #[inline] - fn heap_size(&self, callback: F) { - self.inner.heap_size(callback); + fn index(&self, index: usize) -> Self::ReadItem<'_> { + // SAFETY: All Push implementations only accept correct utf8 data + unsafe { std::str::from_utf8_unchecked(self.inner.index(index)) } } #[inline] @@ -100,6 +94,26 @@ where } } +impl Len for StringRegion { + #[inline] + fn len(&self) -> usize { + self.inner.len() + } +} + +impl HeapSize for StringRegion { + fn heap_size(&self, callback: F) { + self.inner.heap_size(callback); + } +} + +impl Clear for StringRegion { + #[inline] + fn clear(&mut self) { + self.inner.clear(); + } +} + impl RegionPreference for String { type Owned = Self; type Region = StringRegion; @@ -112,27 +126,27 @@ impl RegionPreference for &str { impl Push for StringRegion where - for<'a> R: Region = &'a [u8]> + Push<&'a [u8]> + 'a, + Self: for<'a> Push<&'a str>, { #[inline] - fn push(&mut self, item: String) -> as Region>::Index { + fn push(&mut self, item: String) { self.push(item.as_str()) } } impl Push<&String> for StringRegion where - for<'a> R: Region = &'a [u8]> + Push<&'a [u8]> + 'a, + Self: for<'a> Push<&'a str>, { #[inline] - fn push(&mut self, item: &String) -> as Region>::Index { + fn push(&mut self, item: &String) { self.push(item.as_str()) } } impl<'b, R> ReserveItems<&'b String> for StringRegion where - for<'a> R: Region = &'a [u8]> + ReserveItems<&'a [u8]> + 'a, + for<'a> R: ReserveItems<&'a [u8]> + 'a, { #[inline] fn reserve_items(&mut self, items: I) @@ -145,27 +159,27 @@ where impl Push<&str> for StringRegion where - for<'a> R: Region = &'a [u8]> + Push<&'a [u8]> + 'a, + for<'a> R: Push<&'a [u8]> + 'a, { #[inline] - fn push(&mut self, item: &str) -> as Region>::Index { + fn push(&mut self, item: &str) { self.inner.push(item.as_bytes()) } } impl Push<&&str> for StringRegion where - for<'a> R: Region = &'a [u8]> + Push<&'a [u8]> + 'a, + for<'a> R: Push<&'a [u8]> + 'a, { #[inline] - fn push(&mut self, item: &&str) -> as Region>::Index { + fn push(&mut self, item: &&str) { self.push(*item) } } impl<'b, R> ReserveItems<&'b str> for StringRegion where - for<'a> R: Region = &'a [u8]> + ReserveItems<&'a [u8]> + 'a, + for<'a> R: ReserveItems<&'a [u8]> + 'a, { #[inline] fn reserve_items(&mut self, items: I) @@ -178,7 +192,7 @@ where impl<'a, 'b: 'a, R> ReserveItems<&'a &'b str> for StringRegion where - for<'c> R: Region = &'c [u8]> + ReserveItems<&'c [u8]> + 'c, + for<'c> R: ReserveItems<&'c [u8]> + 'c, { #[inline] fn reserve_items(&mut self, items: I) @@ -191,13 +205,13 @@ where #[cfg(test)] mod tests { - use crate::{IntoOwned, Push, Region, ReserveItems, StringRegion}; + use crate::{HeapSize, Index, IntoOwned, Push, ReserveItems, StringRegion}; #[test] fn test_inner() { let mut r = ::default(); - let index = r.push("abc"); - assert_eq!(r.index(index), "abc"); + r.push("abc"); + assert_eq!(r.index(0), "abc"); } #[test] @@ -249,10 +263,10 @@ mod tests { fn owned() { let mut r = ::default(); - let idx = r.push("abc"); - let reference = r.index(idx); + r.push("abc"); + let reference = r.index(0); let owned = reference.into_owned(); - let idx = r.push(owned); - assert_eq!("abc", r.index(idx)); + r.push(owned); + assert_eq!("abc", r.index(1)); } } diff --git a/src/impls/tuple.rs b/src/impls/tuple.rs index 2348fb1..709bae0 100644 --- a/src/impls/tuple.rs +++ b/src/impls/tuple.rs @@ -4,7 +4,7 @@ use paste::paste; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems}; +use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems, Clear, Len, HeapSize, Index}; /// The macro creates the region implementation for tuples macro_rules! tuple_flatcontainer { @@ -24,10 +24,7 @@ macro_rules! tuple_flatcontainer { } #[allow(non_snake_case)] - impl<$($name: Region + Clone),*> Clone for []<$($name),*> - where - $(<$name as Region>::Index: crate::Index),* - { + impl<$($name: Clone),*> Clone for []<$($name),*> { fn clone(&self) -> Self { Self { $([]: self.[].clone(),)* @@ -40,15 +37,7 @@ macro_rules! tuple_flatcontainer { } #[allow(non_snake_case)] - impl<$($name: Region),*> Region for []<$($name),*> - where - $(<$name as Region>::Index: crate::Index),* - { - type Owned = ($($name::Owned,)*); - type ReadItem<'a> = ($($name::ReadItem<'a>,)*) where Self: 'a; - - type Index = ($($name::Index,)*); - + impl<$($name: Region),*> Region for []<$($name),*> { #[inline] fn merge_regions<'a>(regions: impl Iterator + Clone) -> Self where @@ -58,14 +47,6 @@ macro_rules! tuple_flatcontainer { $([]: $name::merge_regions(regions.clone().map(|r| &r.[]))),* } } - - #[inline] fn index(&self, index: Self::Index) -> Self::ReadItem<'_> { - let ($($name,)*) = index; - ( - $(self.[].index($name),)* - ) - } - #[inline(always)] fn reserve_regions<'a, It>(&mut self, regions: It) where @@ -74,15 +55,17 @@ macro_rules! tuple_flatcontainer { { $(self.[].reserve_regions(regions.clone().map(|r| &r.[]));)* } + } - #[inline(always)] - fn clear(&mut self) { - $(self.[].clear();)* - } + #[allow(non_snake_case)] + impl<$($name: Index),*> Index for []<$($name),*> { + type Owned = ($($name::Owned,)*); + type ReadItem<'a> = ($($name::ReadItem<'a>,)*) where Self: 'a; - #[inline] - fn heap_size(&self, mut callback: Fn) { - $(self.[].heap_size(&mut callback);)* + #[inline] fn index(&self, index: usize) -> Self::ReadItem<'_> { + ( + $(self.[].index(index),)* + ) } #[inline] @@ -94,6 +77,34 @@ macro_rules! tuple_flatcontainer { } } + #[allow(non_snake_case)] + impl<$($name: Clear),*> Clear for []<$($name),*> { + #[inline(always)] + fn clear(&mut self) { + $(self.[].clear();)* + } + } + + #[allow(non_snake_case)] + impl<$($name: Len),*> Len for []<$($name),*> { + #[inline(always)] + fn len(&self) -> usize { + self.0.len() + } + #[inline(always)] + fn is_empty(&self) -> bool { + self.0.is_empty() + } + } + + #[allow(non_snake_case)] + impl<$($name: HeapSize),*> HeapSize for []<$($name),*> { + #[inline] + fn heap_size(&self, mut callback: Fn) { + $(self.[].heap_size(&mut callback);)* + } + } + #[allow(non_camel_case_types)] #[allow(non_snake_case)] impl<$($name, [<$name _C>]: Region ),*> Push<($($name,)*)> for []<$([<$name _C>]),*> @@ -101,10 +112,9 @@ macro_rules! tuple_flatcontainer { $([<$name _C>]: Push<$name>),* { #[inline] - fn push(&mut self, item: ($($name,)*)) - -> <[]<$([<$name _C>]),*> as Region>::Index { + fn push(&mut self, item: ($($name,)*)) { let ($($name,)*) = item; - ($(self.[].push($name),)*) + $(self.[].push($name);)* } } @@ -112,13 +122,12 @@ macro_rules! tuple_flatcontainer { #[allow(non_snake_case)] impl<'a, $($name, [<$name _C>]),*> Push<&'a ($($name,)*)> for []<$([<$name _C>]),*> where - $([<$name _C>]: Region + Push<&'a $name>),* + $([<$name _C>]: Push<&'a $name>),* { #[inline] - fn push(&mut self, item: &'a ($($name,)*)) - -> <[]<$([<$name _C>]),*> as Region>::Index { + fn push(&mut self, item: &'a ($($name,)*)) { let ($($name,)*) = item; - ($(self.[].push($name),)*) + $(self.[].push($name);)* } } @@ -241,12 +250,12 @@ cfg_if::cfg_if! { #[cfg(test)] mod tests { use crate::impls::tuple::TupleABCRegion; - use crate::{FlatStack, MirrorRegion, Push, Region, StringRegion}; + use crate::{Push, Region, StringRegion}; #[test] fn test_tuple() { let t = (1, 2, 3); - let mut r = , MirrorRegion<_>, MirrorRegion<_>>>::default(); + let mut r = , Vec<_>, Vec<_>>>::default(); let index = r.push(t); assert_eq!(t, r.index(index)); @@ -266,7 +275,7 @@ mod tests { #[test] fn test_nested() { let t = ("abc", 2, 3); - let mut r = , MirrorRegion<_>>>::default(); + let mut r = , Vec<_>>>::default(); let index = r.push(t); assert_eq!(t, r.index(index)); @@ -283,7 +292,7 @@ mod tests { #[test] fn test_heap_size() { let t = ("abc", 2, 3); - let mut r = , MirrorRegion<_>>>::default(); + let mut r = , Vec<_>>>::default(); let _ = r.push(t); diff --git a/src/impls/vec.rs b/src/impls/vec.rs index 712a79d..3aa1f25 100644 --- a/src/impls/vec.rs +++ b/src/impls/vec.rs @@ -1,12 +1,9 @@ //! Definitions to use `Vec` as a region. -use crate::{Push, Region, ReserveItems}; - -impl Region for Vec { - type Owned = T; - type ReadItem<'a> = &'a T where Self: 'a; - type Index = usize; +use crate::{Clear, HeapSize, Index, IndexAs, Len, Push, Region, Reserve, ReserveItems}; +impl Region for Vec { + #[inline(always)] fn merge_regions<'a>(regions: impl Iterator + Clone) -> Self where Self: 'a, @@ -14,10 +11,7 @@ impl Region for Vec { Self::with_capacity(regions.map(Vec::len).sum()) } - fn index(&self, index: Self::Index) -> Self::ReadItem<'_> { - &self[index] - } - + #[inline(always)] fn reserve_regions<'a, I>(&mut self, regions: I) where Self: 'a, @@ -25,16 +19,16 @@ impl Region for Vec { { self.reserve(regions.map(Vec::len).sum()); } +} - fn clear(&mut self) { - self.clear(); - } - - fn heap_size(&self, mut callback: F) { - let size_of_t = std::mem::size_of::(); - callback(self.len() * size_of_t, self.capacity() * size_of_t); +impl Index for Vec { + type Owned = T; + type ReadItem<'a> = &'a T where Self: 'a; + #[inline(always)] + fn index(&self, index: usize) -> Self::ReadItem<'_> { + &self[index] } - + #[inline(always)] fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b> where Self: 'a, @@ -43,28 +37,69 @@ impl Region for Vec { } } +impl IndexAs for Vec { + #[inline(always)] + fn index_as(&self, index: usize) -> T { + self[index] + } +} + impl Push for Vec { - fn push(&mut self, item: T) -> Self::Index { + #[inline(always)] + fn push(&mut self, item: T) { self.push(item); - self.len() - 1 } } impl Push<&T> for Vec { - fn push(&mut self, item: &T) -> Self::Index { + #[inline(always)] + fn push(&mut self, item: &T) { self.push(item.clone()); - self.len() - 1 } } impl Push<&&T> for Vec { - fn push(&mut self, item: &&T) -> Self::Index { + #[inline(always)] + fn push(&mut self, item: &&T) { self.push((*item).clone()); - self.len() - 1 + } +} + +impl Clear for Vec { + #[inline(always)] + fn clear(&mut self) { + self.clear(); + } +} + +impl Len for Vec { + #[inline(always)] + fn len(&self) -> usize { + self.len() + } + #[inline(always)] + fn is_empty(&self) -> bool { + self.is_empty() + } +} + +impl HeapSize for Vec { + #[inline(always)] + fn heap_size(&self, mut callback: F) { + let size_of_t = std::mem::size_of::(); + callback(self.len() * size_of_t, self.capacity() * size_of_t); + } +} + +impl Reserve for Vec { + #[inline(always)] + fn reserve(&mut self, additional: usize) { + self.reserve(additional); } } impl ReserveItems for Vec { + #[inline(always)] fn reserve_items(&mut self, items: I) where I: Iterator + Clone, @@ -75,13 +110,15 @@ impl ReserveItems for Vec { #[cfg(test)] mod tests { + use crate::Index; + #[test] fn vec() { - use crate::{Push, Region, ReserveItems}; + use crate::{Push, ReserveItems}; let mut region = Vec::::new(); - let index = <_ as Push<_>>::push(&mut region, 42); - assert_eq!(region.index(index), &42); + <_ as Push<_>>::push(&mut region, 42); + assert_eq!(region.index(0), &42); let mut region = Vec::::new(); region.push(42); diff --git a/src/lib.rs b/src/lib.rs index 759a508..5b24e06 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,38 +2,18 @@ #![deny(missing_docs)] use std::borrow::Borrow; -use std::fmt::{Debug, Formatter}; - -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; pub mod impls; -use crate::impls::index::IndexContainer; -pub use impls::columns::ColumnsRegion; -pub use impls::mirror::MirrorRegion; -pub use impls::option::OptionRegion; -pub use impls::result::ResultRegion; +// use crate::impls::index::IndexContainer; +// pub use impls::columns::ColumnsRegion; +// pub use impls::mirror::MirrorRegion; +// pub use impls::option::OptionRegion; +// pub use impls::result::ResultRegion; pub use impls::slice::SliceRegion; pub use impls::slice_owned::OwnedRegion; pub use impls::string::StringRegion; -/// An index into a region. Automatically implemented for relevant types. -/// -/// We require an index to be [`Copy`] and to support serde. -#[cfg(feature = "serde")] -pub trait Index: Copy + Serialize + for<'a> Deserialize<'a> {} -#[cfg(feature = "serde")] -impl Deserialize<'a>> Index for T {} - -/// An index into a region. Automatically implemented for relevant types. -/// -/// We require an index to be [`Copy`]. -#[cfg(not(feature = "serde"))] -pub trait Index: Copy {} -#[cfg(not(feature = "serde"))] -impl Index for T {} - /// A region to absorb presented data and present it as a type with a lifetime. /// /// This type absorbs data and provides an index to look up an equivalent representation @@ -41,46 +21,17 @@ impl Index for T {} /// presentation of the data, and what data it can absorb. /// /// Implement the [`Push`] trait for all types that can be copied into a region. -pub trait Region: Default { - /// An owned type that can be constructed from a read item. - type Owned; - - /// The type of the data that one gets out of the container. - type ReadItem<'a>: IntoOwned<'a, Owned = Self::Owned> - where - Self: 'a; - - /// The type to index into the container. Should be treated - /// as an opaque type, even if known. - type Index: Index; - +pub trait Region { /// Construct a region that can absorb the contents of `regions` in the future. fn merge_regions<'a>(regions: impl Iterator + Clone) -> Self where Self: 'a; - /// Index into the container. The index must be obtained by - /// pushing data into the container. - #[must_use] - fn index(&self, index: Self::Index) -> Self::ReadItem<'_>; - /// Ensure that the region can absorb the items of `regions` without reallocation fn reserve_regions<'a, I>(&mut self, regions: I) where Self: 'a, I: Iterator + Clone; - - /// Remove all elements from this region, but retain allocations if possible. - fn clear(&mut self); - - /// Heap size, size - capacity - fn heap_size(&self, callback: F); - - /// Converts a read item into one with a narrower lifetime. - #[must_use] - fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b> - where - Self: 'a; } /// A trait to let types express a default container type and an owned type, which can @@ -89,14 +40,14 @@ pub trait Region: Default { /// # Example /// /// ``` -/// # use flatcontainer::{FlatStack, RegionPreference}; -/// let _ = FlatStack::<<((Vec, &[usize]), Option, Result) as RegionPreference>::Region>::default(); +/// # use flatcontainer::{RegionPreference}; +/// let _ = <<((Vec, &[usize]), Option, Result) as RegionPreference>::Region>::default(); /// ``` pub trait RegionPreference { /// The owned type of the region. type Owned; /// The recommended container type. - type Region: Region; + type Region: Index; } impl RegionPreference for &T { @@ -104,18 +55,16 @@ impl RegionPreference for &T { type Region = T::Region; } -/// Push an item `T` into a region. -pub trait Push: Region { - /// Push `item` into self, returning an index that allows to look up the - /// corresponding read item. - #[must_use] - fn push(&mut self, item: T) -> Self::Index; +/// Push an item `T` into a container. +pub trait Push { + /// Push `item` into self. + fn push(&mut self, item: T); } /// Reserve space in the receiving region. /// /// Closely related to [`Push`], but separate because target type is likely different. -pub trait ReserveItems: Region { +pub trait ReserveItems { /// Ensure that the region can absorb `items` without reallocation. fn reserve_items(&mut self, items: I) where @@ -156,7 +105,7 @@ impl<'a, T: ToOwned + ?Sized> IntoOwned<'a> for &'a T { owned.borrow() } } - +/* /// A container for indices into a region. #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr( @@ -413,6 +362,7 @@ impl Clone for FlatStack { self.indices.clone_from(&source.indices); } } +*/ /// A type to wrap and push iterators into regions. /// @@ -422,10 +372,85 @@ impl Clone for FlatStack { #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] pub struct PushIter(pub I); +impl IntoIterator for PushIter { + type Item = I::Item; + type IntoIter = I::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +/// TODO +pub trait IndexAs { + /// TODO + fn index_as(&self, index: usize) -> T; +} + +/// TODO +pub trait Len { + /// TODO + fn len(&self) -> usize; + /// TODO + fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +/// TODO +pub trait Reserve { + /// TODO + fn reserve(&mut self, additional: usize); +} + +/// TODO +pub trait WithCapacity { + /// TODO + fn with_capacity(capacity: usize) -> Self; +} + +/// TODO +pub trait Clear { + /// TODO + fn clear(&mut self); +} + +/// TODO +pub trait HeapSize { + /// TODO + fn heap_size(&self, callback: F); +} + +/// TODO +pub trait Index { + /// An owned type that can be constructed from a read item. + type Owned; + /// The type of the data that one gets out of the container. + type ReadItem<'a>: IntoOwned<'a, Owned = Self::Owned> + where + Self: 'a; + /// TODO + fn index(&self, index: usize) -> Self::ReadItem<'_>; + + /// Converts a read item into one with a narrower lifetime. + #[must_use] + fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b> + where + Self: 'a; + // #[inline] + // fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b> + // where + // Self: 'a, + // { + // item + // } +} + +/* #[cfg(test)] mod tests { - use crate::impls::deduplicate::{CollapseSequence, ConsecutiveIndexPairs}; - use crate::impls::tuple::TupleARegion; + // use crate::impls::deduplicate::{CollapseSequence, ConsecutiveIndexPairs}; + // use crate::impls::tuple::TupleARegion; use super::*; @@ -679,3 +704,4 @@ mod tests { let _ = R::reborrow(item) == R::reborrow(IntoOwned::borrow_as(owned)); } } +*/ diff --git a/tests/cow.rs b/tests/cow.rs index d82e5b7..43438af 100644 --- a/tests/cow.rs +++ b/tests/cow.rs @@ -1,6 +1,6 @@ //! What follows is an example of a Cow-like type that can be used to switch between a GAT //! and an owned type at runtime. - +/* use std::fmt::{Debug, Formatter}; use std::marker::PhantomData; @@ -171,3 +171,4 @@ fn test_gat_cow() { assert_eq!("abcdef", item.into_owned()); assert_eq!("abc", c.get(0).into_owned()); } +*/ diff --git a/tests/person.rs b/tests/person.rs index 5f3a43c..9c32b97 100644 --- a/tests/person.rs +++ b/tests/person.rs @@ -1,5 +1,5 @@ //! Test a slightly more struct with nested regions, representing people. - +/* use flatcontainer::{FlatStack, IntoOwned, Push, Region, RegionPreference, ReserveItems}; struct Person { @@ -186,3 +186,4 @@ fn test_person() { assert_eq!(copied_hobby, hobby); } } +*/ diff --git a/tests/recursive.rs b/tests/recursive.rs index 65e4cd1..ef229c1 100644 --- a/tests/recursive.rs +++ b/tests/recursive.rs @@ -1,5 +1,5 @@ //! Demonstration of how to encode recursive data structures. - +/* use flatcontainer::impls::deduplicate::ConsecutiveIndexPairs; use flatcontainer::{IntoOwned, Push, Region, StringRegion}; @@ -149,3 +149,4 @@ fn recursive() { println!("{region:?}"); } +*/