use arrow_schema::{ArrowError, FieldRef};
use crate::array::ArrayRef;
pub trait ArrayReader: Iterator<Item = Result<ArrayRef, ArrowError>> {
fn field(&self) -> &FieldRef;
}
impl<R: ArrayReader + ?Sized> ArrayReader for Box<R> {
fn field(&self) -> &FieldRef {
self.as_ref().field()
}
}
pub struct ArrayIterator<I>
where
I: IntoIterator<Item = Result<ArrayRef, ArrowError>>,
{
inner: I::IntoIter,
inner_field: FieldRef,
}
impl<I> ArrayIterator<I>
where
I: IntoIterator<Item = Result<ArrayRef, ArrowError>>,
{
pub fn new(iter: I, field: FieldRef) -> Self {
Self {
inner: iter.into_iter(),
inner_field: field,
}
}
}
impl<I> Iterator for ArrayIterator<I>
where
I: IntoIterator<Item = Result<ArrayRef, ArrowError>>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<I> ArrayReader for ArrayIterator<I>
where
I: IntoIterator<Item = Result<ArrayRef, ArrowError>>,
{
fn field(&self) -> &FieldRef {
&self.inner_field
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use arrow_schema::{ArrowError, DataType, Field};
use crate::array::{ArrayRef, Int32Array};
use crate::{ArrayIterator, ArrayReader};
fn test_field() -> Arc<Field> {
Arc::new(Field::new("values", DataType::Int32, true))
}
#[test]
fn array_iterator_reports_its_field_and_yields_its_arrays() {
let field = test_field();
let a: ArrayRef = Arc::new(Int32Array::from(vec![1, 2]));
let b: ArrayRef = Arc::new(Int32Array::from(vec![3]));
let mut reader = ArrayIterator::new(
vec![a.clone(), b.clone()].into_iter().map(Ok),
field.clone(),
);
assert_eq!(reader.field(), &field);
assert_eq!(&reader.next().unwrap().unwrap(), &a);
assert_eq!(&reader.next().unwrap().unwrap(), &b);
assert!(reader.next().is_none());
}
#[test]
fn array_iterator_delegates_size_hint() {
let arrays: Vec<Result<ArrayRef, ArrowError>> =
vec![Ok(Arc::new(Int32Array::from(vec![1])) as ArrayRef)];
let reader = ArrayIterator::new(arrays, test_field());
assert_eq!(reader.size_hint(), (1, Some(1)));
}
#[test]
fn boxed_array_reader_forwards_field() {
let field = test_field();
let reader = ArrayIterator::new(std::iter::empty(), field.clone());
let boxed: Box<dyn ArrayReader + Send> = Box::new(reader);
assert_eq!(boxed.field(), &field);
}
}