diff --git a/src/impls/codec.rs b/src/impls/codec.rs index b51e6e7..e643703 100644 --- a/src/impls/codec.rs +++ b/src/impls/codec.rs @@ -71,7 +71,7 @@ fn consolidate_slice(slice: &mut [(T, usize)]) -> usize { } /// A region that encodes its data in a codec `C`. -#[derive(Default, Debug)] +#[derive(Default, Debug, Clone)] pub struct CodecRegion> { inner: R, codec: C, diff --git a/src/impls/columns.rs b/src/impls/columns.rs index e745ba9..efcf769 100644 --- a/src/impls/columns.rs +++ b/src/impls/columns.rs @@ -48,7 +48,7 @@ use crate::{CopyOnto, OwnedRegion, Region}; /// assert!(row.iter().copied().eq(r.index(index).iter())); /// } /// ``` -#[derive(Debug)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde", diff --git a/src/impls/offsets.rs b/src/impls/offsets.rs index b51c131..8ee853e 100644 --- a/src/impls/offsets.rs +++ b/src/impls/offsets.rs @@ -34,7 +34,7 @@ pub trait OffsetContainer: Default + Extend { /// A container for offsets that can represent strides of offsets. /// /// Does not implement `OffsetContainer` because it cannot accept arbitrary pushes. -#[derive(Debug, Default)] +#[derive(Eq, PartialEq, Debug, Default, Clone, Copy)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum OffsetStride { /// No push has occurred. @@ -136,7 +136,7 @@ impl OffsetStride { } /// A list of unsigned integers that uses `u32` elements as long as they are small enough, and switches to `u64` once they are not. -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug, Default)] +#[derive(Eq, PartialEq, Clone, Debug, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct OffsetList { /// Offsets that fit within a `u32`. @@ -216,7 +216,7 @@ impl OffsetList { /// An offset container implementation that first tries to recognize strides, and then spilles into /// a regular offset list. -#[derive(Default, Debug)] +#[derive(Eq, PartialEq, Default, Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct OffsetOptimized { strided: OffsetStride, diff --git a/src/impls/slice.rs b/src/impls/slice.rs index 7de69ee..50ed413 100644 --- a/src/impls/slice.rs +++ b/src/impls/slice.rs @@ -190,12 +190,18 @@ impl<'a, C: Region, O: OffsetContainer> IntoIterator for ReadSlice<'a, } /// An iterator over the items read from a slice region. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct ReadSliceIter<'a, C: Region, O: OffsetContainer>( &'a SliceRegion, Range, ); +impl<'a, C: Region, O: OffsetContainer> Clone for ReadSliceIter<'a, C, O> { + fn clone(&self) -> Self { + Self(self.0, self.1.clone()) + } +} + impl<'a, C: Region, O: OffsetContainer> Iterator for ReadSliceIter<'a, C, O> { type Item = C::ReadItem<'a>; @@ -361,6 +367,23 @@ where } } +impl ReserveItems> for ReadSlice<'_, R, O> +where + for<'a> R::ReadItem<'a>: ReserveItems, + R: Region, + O: OffsetContainer, +{ + fn reserve_items(target: &mut SliceRegion, items: I) + where + I: Iterator + Clone, + { + target + .slices + .reserve(items.clone().map(|read_slice| read_slice.len()).sum()); + ReserveItems::reserve_items(&mut target.inner, items.flatten()); + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/impls/tuple.rs b/src/impls/tuple.rs index ff62d67..600960c 100644 --- a/src/impls/tuple.rs +++ b/src/impls/tuple.rs @@ -109,6 +109,22 @@ macro_rules! tuple_flatcontainer { tuple_flatcontainer!(reserve_items target items $($name)* @ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31); } } + + #[allow(non_camel_case_types)] + #[allow(non_snake_case)] + impl<$($name, [<$name _C>]: Region ),*> + ReserveItems<[]<$([<$name _C>]),*>> + for ($($name,)*) + where + $($name: ReserveItems<[<$name _C>]>),* + { + fn reserve_items(target: &mut []<$([<$name _C>]),*>, items: It) + where + It: Iterator + Clone + { + tuple_flatcontainer!(reserve_items_owned target items $($name)* @ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31); + } + } } ); (reserve_items $target:ident $items:ident $name0:ident $($name:ident)* @ $num0:tt $($num:tt)*) => { @@ -120,6 +136,15 @@ macro_rules! tuple_flatcontainer { } }; (reserve_items $target:ident $items:ident @ $($num:tt)*) => {}; + (reserve_items_owned $target:ident $items:ident $name0:ident $($name:ident)* @ $num0:tt $($num:tt)*) => { + paste! { + ReserveItems::reserve_items(&mut $target.[], $items.clone().map(|i| { + i.$num0 + })); + tuple_flatcontainer!(reserve_items_owned $target $items $($name)* @ $($num)*); + } + }; + (reserve_items_owned $target:ident $items:ident @ $($num:tt)*) => {}; } tuple_flatcontainer!(A); @@ -162,7 +187,7 @@ cfg_if::cfg_if! { #[cfg(test)] mod tests { use crate::impls::tuple::TupleABCRegion; - use crate::{CopyOnto, MirrorRegion, Region, StringRegion}; + use crate::{CopyOnto, FlatStack, MirrorRegion, Region, StringRegion}; #[test] fn test_tuple() { @@ -221,4 +246,12 @@ mod tests { assert!(cap > 0); assert!(cnt > 0); } + #[test] + fn test_reserve_items() { + let mut c = FlatStack::default_impl::<(usize, String, Vec)>(); + c.copy((1, format!("Hello"), &["abc"])); + + let mut c2 = FlatStack::default_impl::<(usize, String, Vec)>(); + c2.reserve_items(c.iter()); + } } diff --git a/src/lib.rs b/src/lib.rs index 493208a..b84f7fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -278,6 +278,15 @@ impl<'a, R: Region> Iterator for Iter<'a, R> { impl ExactSizeIterator for Iter<'_, R> {} +impl Clone for Iter<'_, R> { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + region: self.region, + } + } +} + impl> FromIterator for FlatStack { fn from_iter>(iter: I) -> Self { let iter = iter.into_iter(); @@ -287,14 +296,12 @@ impl> FromIterator for FlatStack { } } -impl Clone for FlatStack -where - for<'a> R::ReadItem<'a>: CopyOnto, -{ +impl Clone for FlatStack { fn clone(&self) -> Self { - let mut clone = Self::merge_capacity(std::iter::once(self)); - clone.extend(self.iter()); - clone + Self { + region: self.region.clone(), + indices: self.indices.clone(), + } } }