From 2403fd3357270ffaa71e3df917514d7e4fee47b5 Mon Sep 17 00:00:00 2001 From: Moritz Hoffmann Date: Tue, 13 Feb 2024 21:23:32 -0500 Subject: [PATCH] Explicit column iterator; support copying iterators to columns Signed-off-by: Moritz Hoffmann --- src/impls/columns.rs | 108 ++++++++++++++++++++++++++++++++++----- src/impls/deduplicate.rs | 1 + src/impls/slice_copy.rs | 5 +- src/lib.rs | 7 +++ 4 files changed, 105 insertions(+), 16 deletions(-) diff --git a/src/impls/columns.rs b/src/impls/columns.rs index e11c959..2cfbc18 100644 --- a/src/impls/columns.rs +++ b/src/impls/columns.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use crate::impls::deduplicate::ConsecutiveOffsetPairs; use crate::impls::offsets::OffsetOptimized; -use crate::impls::slice_copy::CopyIter; +use crate::CopyIter; use crate::{CopyOnto, CopyRegion, Index, Region}; /// A region that can store a variable number of elements per row. @@ -129,7 +129,6 @@ where } /// Read the values of a row. -#[derive(Copy)] pub struct ReadColumns<'a, R, Idx> where R: Region, @@ -147,13 +146,17 @@ where Idx: Index, { fn clone(&self) -> Self { - Self { - columns: self.columns, - index: self.index, - } + *self } } +impl<'a, R, Idx> Copy for ReadColumns<'a, R, Idx> +where + R: Region, + Idx: Index, +{ +} + impl<'a, R, Idx> Debug for ReadColumns<'a, R, Idx> where R: Region, @@ -161,7 +164,7 @@ where Idx: Index, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_list().entries(self.iter()).finish() + f.debug_list().entries(self).finish() } } @@ -171,11 +174,8 @@ where Idx: Index, { /// Iterate the individual values of a row. - pub fn iter(&self) -> impl Iterator> { - self.index - .iter() - .zip(self.columns) - .map(|(idx, r)| r.index(*idx)) + pub fn iter(&'a self) -> ReadColumnsIter<'a, R, Idx> { + self.into_iter() } /// Get the element at `offset`. @@ -194,6 +194,38 @@ where } } +impl<'a, R, Idx> IntoIterator for &ReadColumns<'a, R, Idx> +where + R: Region, + Idx: Index, +{ + type Item = R::ReadItem<'a>; + type IntoIter = ReadColumnsIter<'a, R, Idx>; + + fn into_iter(self) -> Self::IntoIter { + ReadColumnsIter { + iter: self.index.iter().zip(self.columns.iter()), + } + } +} + +/// An iterator over the elements of a row. +pub struct ReadColumnsIter<'a, R, Idx> { + iter: std::iter::Zip, std::slice::Iter<'a, R>>, +} + +impl<'a, R, Idx> Iterator for ReadColumnsIter<'a, R, Idx> +where + R: Region, + Idx: Index, +{ + type Item = R::ReadItem<'a>; + + fn next(&mut self) -> Option { + self.iter.next().map(|(&i, r)| r.index(i)) + } +} + impl<'a, R, Idx> CopyOnto> for ReadColumns<'a, R, Idx> where R: Region, @@ -285,10 +317,34 @@ where } } +impl CopyOnto> for CopyIter +where + R: Region, + Idx: Index, + T: CopyOnto, + I: IntoIterator, +{ + #[inline] + fn copy_onto( + self, + target: &mut ColumnsRegion, + ) -> as Region>::Index { + let iter = self.0.into_iter().enumerate().map(|(index, value)| { + // Ensure all required regions exist. + if target.inner.len() <= index { + target.inner.push(R::default()); + } + value.copy_onto(&mut target.inner[index]) + }); + CopyIter(iter).copy_onto(&mut target.indices) + } +} + #[cfg(test)] mod tests { use crate::impls::columns::ColumnsRegion; use crate::impls::deduplicate::{CollapseSequence, ConsecutiveOffsetPairs}; + use crate::CopyIter; use crate::{CopyOnto, MirrorRegion, Region, StringRegion}; #[test] @@ -393,4 +449,32 @@ mod tests { println!("{r:?}"); } + + #[test] + fn test_ragged_str_iter() { + let data = [ + vec![], + vec!["1"], + vec!["2", "3"], + vec!["4", "5", "6"], + vec!["7", "8"], + vec!["9"], + vec![], + ]; + + let mut r = ColumnsRegion::, _>::default(); + + let mut indices = Vec::with_capacity(data.len()); + + for row in &data { + let index = CopyIter(row.iter()).copy_onto(&mut r); + indices.push(index); + } + + for (&index, row) in indices.iter().zip(&data) { + assert!(row.iter().copied().eq(r.index(index).iter())); + } + + println!("{r:?}"); + } } diff --git a/src/impls/deduplicate.rs b/src/impls/deduplicate.rs index 2f4cda2..e5f18ed 100644 --- a/src/impls/deduplicate.rs +++ b/src/impls/deduplicate.rs @@ -152,6 +152,7 @@ impl, O: OffsetContainer> Region impl, O: OffsetContainer, T: CopyOnto> CopyOnto> for T { + #[inline] fn copy_onto( self, target: &mut ConsecutiveOffsetPairs, diff --git a/src/impls/slice_copy.rs b/src/impls/slice_copy.rs index 9309c53..bde5234 100644 --- a/src/impls/slice_copy.rs +++ b/src/impls/slice_copy.rs @@ -3,7 +3,7 @@ #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::{CopyOnto, Region, ReserveItems}; +use crate::{CopyIter, CopyOnto, Region, ReserveItems}; /// A container for [`Copy`] types. /// @@ -108,9 +108,6 @@ impl ReserveItems> for &Vec { } } -/// A type to wrap iterators. -pub struct CopyIter(pub I); - impl> CopyOnto> for CopyIter where T: Copy, diff --git a/src/lib.rs b/src/lib.rs index 7aa5822..fe60cae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -303,6 +303,13 @@ impl Clone for FlatStack { } } +/// A type to wrap and copy iterators onto regions. +/// +/// This only exists to avoid blanket implementations that might conflict with more specific +/// implementations offered by some regions. +#[repr(transparent)] +pub struct CopyIter(pub I); + #[cfg(test)] mod tests { use crate::impls::deduplicate::{CollapseSequence, ConsecutiveOffsetPairs};