use crate::array::array::ArrayAccessor;
use crate::array::{BasicDecimalArray, Decimal256Array};
use super::{
Array, BooleanArray, Decimal128Array, GenericBinaryArray, GenericListArray,
GenericStringArray, PrimitiveArray,
};
#[derive(Debug)]
pub struct ArrayIter<T: ArrayAccessor> {
array: T,
current: usize,
current_end: usize,
}
impl<T: ArrayAccessor> ArrayIter<T> {
pub fn new(array: T) -> Self {
let len = array.len();
ArrayIter {
array,
current: 0,
current_end: len,
}
}
}
impl<T: ArrayAccessor> Iterator for ArrayIter<T> {
type Item = Option<T::Item>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.current == self.current_end {
None
} else if self.array.is_null(self.current) {
self.current += 1;
Some(None)
} else {
let old = self.current;
self.current += 1;
unsafe { Some(Some(self.array.value_unchecked(old))) }
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(
self.array.len() - self.current,
Some(self.array.len() - self.current),
)
}
}
impl<T: ArrayAccessor> DoubleEndedIterator for ArrayIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.current_end == self.current {
None
} else {
self.current_end -= 1;
Some(if self.array.is_null(self.current_end) {
None
} else {
unsafe { Some(self.array.value_unchecked(self.current_end)) }
})
}
}
}
impl<T: ArrayAccessor> ExactSizeIterator for ArrayIter<T> {}
pub type PrimitiveIter<'a, T> = ArrayIter<&'a PrimitiveArray<T>>;
pub type BooleanIter<'a> = ArrayIter<&'a BooleanArray>;
pub type GenericStringIter<'a, T> = ArrayIter<&'a GenericStringArray<T>>;
pub type GenericBinaryIter<'a, T> = ArrayIter<&'a GenericBinaryArray<T>>;
pub type GenericListArrayIter<'a, O> = ArrayIter<&'a GenericListArray<O>>;
pub type Decimal128Iter<'a> = ArrayIter<&'a Decimal128Array>;
pub type Decimal256Iter<'a> = ArrayIter<&'a Decimal256Array>;
#[derive(Debug)]
#[deprecated(note = "Please use `Decimal128Iter` instead. \
`DecimalIter` iterates `Decimal128` values as i128 values. \
This is kept mostly for back-compatibility purpose. Suggests to use `Decimal128Array.iter()` \
that returns `Decimal128Iter`.")]
pub struct DecimalIter<'a> {
array: &'a Decimal128Array,
current: usize,
current_end: usize,
}
#[allow(deprecated)]
impl<'a> DecimalIter<'a> {
pub fn new(array: &'a Decimal128Array) -> Self {
Self {
array,
current: 0,
current_end: array.len(),
}
}
}
#[allow(deprecated)]
impl<'a> std::iter::Iterator for DecimalIter<'a> {
type Item = Option<i128>;
fn next(&mut self) -> Option<Self::Item> {
if self.current == self.current_end {
None
} else {
let old = self.current;
self.current += 1;
if self.array.is_null(old) {
Some(None)
} else {
Some(Some(self.array.value(old).as_i128()))
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let remain = self.current_end - self.current;
(remain, Some(remain))
}
}
#[allow(deprecated)]
impl<'a> std::iter::ExactSizeIterator for DecimalIter<'a> {}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use crate::array::{ArrayRef, BinaryArray, BooleanArray, Int32Array, StringArray};
#[test]
fn test_primitive_array_iter_round_trip() {
let array = Int32Array::from(vec![Some(0), None, Some(2), None, Some(4)]);
let array = Arc::new(array) as ArrayRef;
let array = array.as_any().downcast_ref::<Int32Array>().unwrap();
let result: Int32Array = array.iter().map(|e| e.map(|e| e + 1)).collect();
let expected = Int32Array::from(vec![Some(1), None, Some(3), None, Some(5)]);
assert_eq!(result, expected);
let result: Int32Array = array.iter().rev().collect();
let rev_array = Int32Array::from(vec![Some(4), None, Some(2), None, Some(0)]);
assert_eq!(result, rev_array);
let _ = array.iter().rposition(|opt_b| opt_b == Some(1));
}
#[test]
fn test_double_ended() {
let array = Int32Array::from(vec![Some(0), None, Some(2), None, Some(4)]);
let mut a = array.iter();
assert_eq!(a.next(), Some(Some(0)));
assert_eq!(a.next(), Some(None));
assert_eq!(a.next_back(), Some(Some(4)));
assert_eq!(a.next_back(), Some(None));
assert_eq!(a.next_back(), Some(Some(2)));
assert_eq!(a.next_back(), None);
assert_eq!(a.next(), None);
}
#[test]
fn test_string_array_iter_round_trip() {
let array =
StringArray::from(vec![Some("a"), None, Some("aaa"), None, Some("aaaaa")]);
let array = Arc::new(array) as ArrayRef;
let array = array.as_any().downcast_ref::<StringArray>().unwrap();
let result: StringArray = array
.iter()
.map(|e| {
e.map(|e| {
let mut a = e.to_string();
a.push('b');
a
})
})
.collect();
let expected =
StringArray::from(vec![Some("ab"), None, Some("aaab"), None, Some("aaaaab")]);
assert_eq!(result, expected);
let result: StringArray = array.iter().rev().collect();
let rev_array =
StringArray::from(vec![Some("aaaaa"), None, Some("aaa"), None, Some("a")]);
assert_eq!(result, rev_array);
let _ = array.iter().rposition(|opt_b| opt_b == Some("a"));
}
#[test]
fn test_binary_array_iter_round_trip() {
let array = BinaryArray::from(vec![
Some(b"a" as &[u8]),
None,
Some(b"aaa"),
None,
Some(b"aaaaa"),
]);
let result: BinaryArray = array.iter().collect();
assert_eq!(result, array);
let result: BinaryArray = array.iter().rev().collect();
let rev_array = BinaryArray::from(vec![
Some(b"aaaaa" as &[u8]),
None,
Some(b"aaa"),
None,
Some(b"a"),
]);
assert_eq!(result, rev_array);
let _ = array.iter().rposition(|opt_b| opt_b == Some(&[9]));
}
#[test]
fn test_boolean_array_iter_round_trip() {
let array = BooleanArray::from(vec![Some(true), None, Some(false)]);
let result: BooleanArray = array.iter().collect();
assert_eq!(result, array);
let result: BooleanArray = array.iter().rev().collect();
let rev_array = BooleanArray::from(vec![Some(false), None, Some(true)]);
assert_eq!(result, rev_array);
let _ = array.iter().rposition(|opt_b| opt_b == Some(true));
}
}