From 4f6e177edef7187a0999fe88e40564474febaae3 Mon Sep 17 00:00:00 2001 From: Matthijs Brobbel Date: Wed, 30 Jun 2021 01:41:05 +0200 Subject: [PATCH] Implement iterators for variable size array types --- src/array/boolean.rs | 11 +-- src/array/fixed_size_list.rs | 12 ---- src/array/mod.rs | 9 +-- src/array/variable_size_binary.rs | 108 +++++++++++++++++++++++++++++ src/array/variable_size_list.rs | 111 +++++++++++++++++++++++++++++- src/buffer.rs | 19 +---- src/offset.rs | 8 ++- src/validity.rs | 5 +- 8 files changed, 232 insertions(+), 51 deletions(-) diff --git a/src/array/boolean.rs b/src/array/boolean.rs index b9eeb567..1db617f6 100644 --- a/src/array/boolean.rs +++ b/src/array/boolean.rs @@ -58,15 +58,6 @@ impl FromIterator> for BooleanArray { } } -impl<'a> FromIterator<&'a Option> for BooleanArray { - fn from_iter(iter: I) -> Self - where - I: IntoIterator>, - { - Self(iter.into_iter().copied().collect()) - } -} - impl<'a> IntoIterator for &'a BooleanArray { type Item = bool; type IntoIter = <&'a Bitmap as IntoIterator>::IntoIter; @@ -106,7 +97,7 @@ mod tests { assert_eq!(vec, boolean_array.into_iter().collect::>()); let vec = vec![Some(false), Some(true), None, Some(true), None]; - let boolean_array = vec.iter().collect::>(); + let boolean_array = vec.iter().copied().collect::>(); assert_eq!( vec, boolean_array.into_iter().collect::>>() diff --git a/src/array/fixed_size_list.rs b/src/array/fixed_size_list.rs index 7f6bd53d..443b3449 100644 --- a/src/array/fixed_size_list.rs +++ b/src/array/fixed_size_list.rs @@ -102,18 +102,6 @@ where } } -impl<'a, T, const N: usize, const M: bool> IntoIterator for &'a FixedSizeListArray -where - T: Array, -{ - type Item = T; //[T; N]; - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - todo!() - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/array/mod.rs b/src/array/mod.rs index 5a63cf28..e33f4fdc 100644 --- a/src/array/mod.rs +++ b/src/array/mod.rs @@ -17,17 +17,14 @@ mod r#struct; pub use r#struct::*; /// Types for which sequences of values can be stored in arrays. -pub trait ArrayType // where -// for<'a> &'a Self::Array: IntoIterator, -{ +pub trait ArrayType { /// Array type used for this type. type Array: Array; } /// A sequence of values with known length all having the same type. -pub trait Array // where -// for<'a> &'a Self: IntoIterator, -{ +// todo(mb): https://github.com/rust-lang/rust/issues/20671 +pub trait Array { /// [Validity](crate::Validity) of the array. // todo(mb): GATs type Validity: ArrayData; diff --git a/src/array/variable_size_binary.rs b/src/array/variable_size_binary.rs index 0b11141f..d964cf4d 100644 --- a/src/array/variable_size_binary.rs +++ b/src/array/variable_size_binary.rs @@ -109,6 +109,84 @@ where } } +/// Iterator over elements of an array with variable-sized binary data. +pub struct VariableSizeBinaryArrayIter<'a, T, const N: bool> +where + T: OffsetValue, + &'a Offset: IntoIterator, +{ + data: &'a [u8], + offset: <&'a Offset as IntoIterator>::IntoIter, +} + +impl<'a, T> Iterator for VariableSizeBinaryArrayIter<'a, T, false> +where + T: OffsetValue, + &'a Offset: IntoIterator, +{ + type Item = &'a [u8]; + + fn next(&mut self) -> Option { + self.offset + .next() + .map(|(start, end)| &self.data[start..end]) + } + + fn size_hint(&self) -> (usize, Option) { + self.offset.size_hint() + } +} + +impl<'a, T> IntoIterator for &'a VariableSizeBinaryArray +where + T: OffsetValue, + &'a Offset: IntoIterator, +{ + type Item = &'a [u8]; + type IntoIter = VariableSizeBinaryArrayIter<'a, T, false>; + + fn into_iter(self) -> Self::IntoIter { + VariableSizeBinaryArrayIter { + data: &self.data, + offset: self.offset.into_iter(), + } + } +} + +impl<'a, T> Iterator for VariableSizeBinaryArrayIter<'a, T, true> +where + T: OffsetValue, + &'a Offset: IntoIterator>, +{ + type Item = Option<&'a [u8]>; + + fn next(&mut self) -> Option { + self.offset + .next() + .map(|opt| opt.map(|(start, end)| &self.data[start..end])) + } + + fn size_hint(&self) -> (usize, Option) { + self.offset.size_hint() + } +} + +impl<'a, T> IntoIterator for &'a VariableSizeBinaryArray +where + T: OffsetValue, + &'a Offset: IntoIterator>, +{ + type Item = Option<&'a [u8]>; + type IntoIter = VariableSizeBinaryArrayIter<'a, T, true>; + + fn into_iter(self) -> Self::IntoIter { + VariableSizeBinaryArrayIter { + data: &self.data, + offset: self.offset.into_iter(), + } + } +} + /// Array with variable sized binary data. Uses [i32] offsets. pub type BinaryArray = VariableSizeBinaryArray; @@ -139,4 +217,34 @@ mod tests { let array = vec.into_iter().collect::>(); assert_eq!(array.len(), 6); } + + #[test] + fn into_iter() { + let x = vec![1u8, 2, 3, 4, 5]; + let y = vec![1u8, 2, 3, 4]; + let z = vec![1u8, 2, 3]; + let vec = vec![&x[..], &y, &z]; + + let array = vec.iter().collect::>(); + let mut iter = array.into_iter(); + assert_eq!(iter.size_hint(), (3, Some(3))); + assert_eq!(iter.next(), Some(&x[..])); + assert_eq!(iter.next(), Some(&y[..])); + assert_eq!(iter.next(), Some(&z[..])); + assert_eq!(iter.next(), None); + + let x = vec![1u8, 2, 3, 4, 5]; + let y = vec![1u8, 2, 3, 4]; + let vec = vec![Some(&x[..]), Some(&y), None, None, Some(&x), Some(&[])]; + let array = vec.into_iter().collect::>(); + let mut iter = array.into_iter(); + assert_eq!(iter.size_hint(), (6, Some(6))); + assert_eq!(iter.next(), Some(Some(&x[..]))); + assert_eq!(iter.next(), Some(Some(&y[..]))); + assert_eq!(iter.next(), Some(None)); + assert_eq!(iter.next(), Some(None)); + assert_eq!(iter.next(), Some(Some(&x[..]))); + assert_eq!(iter.next(), Some(Some(&[] as &[u8]))); + assert_eq!(iter.next(), None); + } } diff --git a/src/array/variable_size_list.rs b/src/array/variable_size_list.rs index 68b4e7d5..3516a965 100644 --- a/src/array/variable_size_list.rs +++ b/src/array/variable_size_list.rs @@ -1,5 +1,5 @@ use crate::{Array, ArrayType, NestedArray, Offset, OffsetValue, Uint8Array}; -use std::iter::FromIterator; +use std::iter::{FromIterator, Skip, Take}; /// Array with variable-sized lists of other array types. /// @@ -143,6 +143,85 @@ where } } +pub struct VariableSizeListArrayIter<'a, T, U, const N: bool> +where + U: OffsetValue, + &'a Offset: IntoIterator, +{ + data: &'a T, + offset: <&'a Offset as IntoIterator>::IntoIter, +} + +impl<'a, T, U> Iterator for VariableSizeListArrayIter<'a, T, U, false> +where + &'a T: IntoIterator, + U: OffsetValue, +{ + type Item = Take::IntoIter>>; + + fn next(&mut self) -> Option { + self.offset + .next() + .map(|(start, end)| self.data.into_iter().skip(start).take(end - start)) + } + + fn size_hint(&self) -> (usize, Option) { + self.offset.size_hint() + } +} + +impl<'a, T, U> IntoIterator for &'a VariableSizeListArray +where + T: Array, + &'a T: IntoIterator, + U: OffsetValue, +{ + type Item = Take::IntoIter>>; + type IntoIter = VariableSizeListArrayIter<'a, T, U, false>; + + fn into_iter(self) -> Self::IntoIter { + VariableSizeListArrayIter { + data: &self.data, + offset: self.offset.into_iter(), + } + } +} + +impl<'a, T, U> Iterator for VariableSizeListArrayIter<'a, T, U, true> +where + &'a T: IntoIterator, + U: OffsetValue, +{ + type Item = Option::IntoIter>>>; + + fn next(&mut self) -> Option { + self.offset + .next() + .map(|opt| opt.map(|(start, end)| self.data.into_iter().skip(start).take(end - start))) + } + + fn size_hint(&self) -> (usize, Option) { + self.offset.size_hint() + } +} + +impl<'a, T, U> IntoIterator for &'a VariableSizeListArray +where + T: Array, + &'a T: IntoIterator, + U: OffsetValue, +{ + type Item = Option::IntoIter>>>; + type IntoIter = VariableSizeListArrayIter<'a, T, U, true>; + + fn into_iter(self) -> Self::IntoIter { + VariableSizeListArrayIter { + data: &self.data, + offset: self.offset.into_iter(), + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -202,4 +281,34 @@ mod tests { assert_eq!(list.child().len(), 6); assert_eq!(list.child().data().len(), 24); } + + #[test] + fn into_iter() { + let x = vec![1u32, 2, 3, 4]; + let y = vec![1u32, 2, 3, 4, 5]; + let vec = vec![x.clone(), y.clone()]; + let list: ListArray, false> = vec.into_iter().collect(); + let mut iter = list.into_iter(); + assert_eq!(iter.size_hint(), (2, Some(2))); + assert_eq!(iter.next().unwrap().collect::>(), x); + assert_eq!(iter.next().unwrap().collect::>(), y); + assert!(iter.next().is_none()); + + let vec = vec![vec![x.clone(), y.clone()]]; + let list: ListArray, false>, false> = + vec.clone().into_iter().collect(); + assert_eq!( + list.into_iter().flatten().flatten().collect::>(), + vec[0].iter().flatten().copied().collect::>() + ); + + let vec = vec![Some(x.clone()), None, Some(y.clone())]; + let list: ListArray, true> = vec.into_iter().collect(); + let mut iter = list.into_iter(); + assert_eq!(iter.size_hint(), (3, Some(3))); + assert_eq!(iter.next().unwrap().unwrap().collect::>(), x); + assert!(iter.next().unwrap().is_none()); + assert_eq!(iter.next().unwrap().unwrap().collect::>(), y); + assert!(iter.next().is_none()); + } } diff --git a/src/buffer.rs b/src/buffer.rs index e681762c..258d6774 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -54,23 +54,6 @@ impl Buffer where T: Primitive, { - /// Extracts a slice containing the entire buffer. - /// - /// Equivalent to `&buffer[..]`. - /// - /// # Examples - /// - /// ``` - /// use narrow::Buffer; - /// - /// let buffer: Buffer<_, 3> = [1u8, 2, 3, 4].iter().copied().collect(); - /// - /// assert_eq!(buffer.as_slice(), &buffer[..]); - /// ``` - pub fn as_slice(&self) -> &[T] { - &self - } - /// Returns an new Buffer. /// todo(mb): document safety issues pub(crate) unsafe fn new_unchecked(ptr: *mut T, len: usize) -> Self { @@ -196,7 +179,7 @@ where T: Primitive, { fn clone(&self) -> Self { - Self::from_slice(self.as_slice()) + Self::from_slice(self) } } diff --git a/src/offset.rs b/src/offset.rs index b989e8b6..92e2274f 100644 --- a/src/offset.rs +++ b/src/offset.rs @@ -151,7 +151,7 @@ where } } -/// Iterator over offsets values. +/// Iterator over offsets values of variable sized arrays. pub struct OffsetIter { pos: Option, iter: T, @@ -203,6 +203,10 @@ where }), ) } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } } impl<'a, T> IntoIterator for &'a Offset @@ -266,7 +270,7 @@ mod tests { assert_eq!(&offset[..], &[0, 1, 3, 6, 10]); let offset: Offset = [Some(3), None, Some(4), Some(0)].iter().copied().collect(); - assert_eq!(offset.data().as_slice(), &[0, 3, 3, 7, 7]); + assert_eq!(&offset.data()[..], &[0, 3, 3, 7, 7]); } #[test] diff --git a/src/validity.rs b/src/validity.rs index 39700120..f6b34bbc 100644 --- a/src/validity.rs +++ b/src/validity.rs @@ -71,6 +71,7 @@ where _ => unsafe { unreachable_unchecked() }, } } + fn is_null(&self, index: usize) -> bool { match (N, &self.0) { (false, _) => false, @@ -174,13 +175,13 @@ mod tests { #[test] fn data() { let valid: Validity, false> = vec![1u8, 2, 3, 4].into_iter().collect(); - assert_eq!(valid.data().as_slice(), &[1, 2, 3, 4]); + assert_eq!(&valid.data()[..], &[1, 2, 3, 4]); let nullable: Validity, true> = vec![Some(1u8), None, Some(3), Some(4)] .into_iter() .collect(); - assert_eq!(nullable.data().as_slice(), &[1, u8::default(), 3, 4]); + assert_eq!(&nullable.data()[..], &[1, u8::default(), 3, 4]); } #[test]