Skip to content

Commit

Permalink
Explicit column iterator; support copying iterators to columns
Browse files Browse the repository at this point in the history
Signed-off-by: Moritz Hoffmann <[email protected]>
  • Loading branch information
antiguru committed Feb 14, 2024
1 parent 7117032 commit 2403fd3
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 16 deletions.
108 changes: 96 additions & 12 deletions src/impls/columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -129,7 +129,6 @@ where
}

/// Read the values of a row.
#[derive(Copy)]
pub struct ReadColumns<'a, R, Idx>
where
R: Region<Index = Idx>,
Expand All @@ -147,21 +146,25 @@ 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<Index = Idx>,
Idx: Index,
{
}

impl<'a, R, Idx> Debug for ReadColumns<'a, R, Idx>
where
R: Region<Index = Idx>,
R::ReadItem<'a>: Debug,
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()
}
}

Expand All @@ -171,11 +174,8 @@ where
Idx: Index,
{
/// Iterate the individual values of a row.
pub fn iter(&self) -> impl Iterator<Item = R::ReadItem<'a>> {
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`.
Expand All @@ -194,6 +194,38 @@ where
}
}

impl<'a, R, Idx> IntoIterator for &ReadColumns<'a, R, Idx>
where
R: Region<Index = Idx>,
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, Idx>, std::slice::Iter<'a, R>>,
}

impl<'a, R, Idx> Iterator for ReadColumnsIter<'a, R, Idx>
where
R: Region<Index = Idx>,
Idx: Index,
{
type Item = R::ReadItem<'a>;

fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(&i, r)| r.index(i))
}
}

impl<'a, R, Idx> CopyOnto<ColumnsRegion<R, Idx>> for ReadColumns<'a, R, Idx>
where
R: Region<Index = Idx>,
Expand Down Expand Up @@ -285,10 +317,34 @@ where
}
}

impl<R, Idx, T, I> CopyOnto<ColumnsRegion<R, Idx>> for CopyIter<I>
where
R: Region<Index = Idx>,
Idx: Index,
T: CopyOnto<R>,
I: IntoIterator<Item = T>,
{
#[inline]
fn copy_onto(
self,
target: &mut ColumnsRegion<R, Idx>,
) -> <ColumnsRegion<R, Idx> 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]
Expand Down Expand Up @@ -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::<ConsecutiveOffsetPairs<StringRegion>, _>::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:?}");
}
}
1 change: 1 addition & 0 deletions src/impls/deduplicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ impl<R: Region<Index = (usize, usize)>, O: OffsetContainer<usize>> Region
impl<R: Region<Index = (usize, usize)>, O: OffsetContainer<usize>, T: CopyOnto<R>>
CopyOnto<ConsecutiveOffsetPairs<R, O>> for T
{
#[inline]
fn copy_onto(
self,
target: &mut ConsecutiveOffsetPairs<R, O>,
Expand Down
5 changes: 1 addition & 4 deletions src/impls/slice_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -108,9 +108,6 @@ impl<T: Copy> ReserveItems<CopyRegion<T>> for &Vec<T> {
}
}

/// A type to wrap iterators.
pub struct CopyIter<I>(pub I);

impl<T, I: IntoIterator<Item = T>> CopyOnto<CopyRegion<T>> for CopyIter<I>
where
T: Copy,
Expand Down
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,13 @@ impl<R: Region> Clone for FlatStack<R> {
}
}

/// 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<I>(pub I);

#[cfg(test)]
mod tests {
use crate::impls::deduplicate::{CollapseSequence, ConsecutiveOffsetPairs};
Expand Down

0 comments on commit 2403fd3

Please sign in to comment.