Skip to main content

arrow_array/
array_reader.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Traits for reading a stream of [`ArrayRef`] that share a single [`FieldRef`].
19
20use arrow_schema::{ArrowError, FieldRef};
21
22use crate::array::ArrayRef;
23
24/// Trait for types that can read `ArrayRef`'s.
25///
26/// This is the array-level counterpart to [`RecordBatchReader`], for streams whose
27/// elements are not record batches.
28///
29/// To create from an iterator, see [ArrayIterator]. To read one from the C Stream Interface,
30/// see [`ffi_stream::ArrayStreamReader`].
31///
32/// [`RecordBatchReader`]: crate::RecordBatchReader
33/// [`ffi_stream::ArrayStreamReader`]: crate::ffi_stream::ArrayStreamReader
34pub trait ArrayReader: Iterator<Item = Result<ArrayRef, ArrowError>> {
35    /// Returns the field of this `ArrayReader`.
36    ///
37    /// Implementation of this trait should guarantee that all `ArrayRef`'s returned by this
38    /// reader have the same field as returned from this method.
39    fn field(&self) -> &FieldRef;
40}
41
42impl<R: ArrayReader + ?Sized> ArrayReader for Box<R> {
43    fn field(&self) -> &FieldRef {
44        self.as_ref().field()
45    }
46}
47
48/// Generic implementation of [ArrayReader] that wraps an iterator.
49///
50/// # Example
51///
52/// ```
53/// # use std::sync::Arc;
54/// # use arrow_array::{ArrayIterator, ArrayReader, ArrayRef, Int32Array};
55/// # use arrow_schema::{DataType, Field};
56/// #
57/// let a: ArrayRef = Arc::new(Int32Array::from(vec![1, 2]));
58/// let b: ArrayRef = Arc::new(Int32Array::from(vec![3, 4]));
59///
60/// let field = Arc::new(Field::new("values", DataType::Int32, false));
61/// let iter = vec![a.clone(), b.clone()].into_iter().map(Ok);
62/// let mut reader = ArrayIterator::new(iter, field.clone());
63///
64/// assert_eq!(reader.field(), &field);
65/// assert_eq!(&reader.next().unwrap().unwrap(), &a);
66/// assert_eq!(&reader.next().unwrap().unwrap(), &b);
67/// assert!(reader.next().is_none());
68/// ```
69pub struct ArrayIterator<I>
70where
71    I: IntoIterator<Item = Result<ArrayRef, ArrowError>>,
72{
73    inner: I::IntoIter,
74    inner_field: FieldRef,
75}
76
77impl<I> ArrayIterator<I>
78where
79    I: IntoIterator<Item = Result<ArrayRef, ArrowError>>,
80{
81    /// Create a new [ArrayIterator].
82    ///
83    /// If `iter` is an infallible iterator, use `.map(Ok)`.
84    pub fn new(iter: I, field: FieldRef) -> Self {
85        Self {
86            inner: iter.into_iter(),
87            inner_field: field,
88        }
89    }
90}
91
92impl<I> Iterator for ArrayIterator<I>
93where
94    I: IntoIterator<Item = Result<ArrayRef, ArrowError>>,
95{
96    type Item = I::Item;
97
98    fn next(&mut self) -> Option<Self::Item> {
99        self.inner.next()
100    }
101
102    fn size_hint(&self) -> (usize, Option<usize>) {
103        self.inner.size_hint()
104    }
105}
106
107impl<I> ArrayReader for ArrayIterator<I>
108where
109    I: IntoIterator<Item = Result<ArrayRef, ArrowError>>,
110{
111    fn field(&self) -> &FieldRef {
112        &self.inner_field
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use std::sync::Arc;
119
120    use arrow_schema::{ArrowError, DataType, Field};
121
122    use crate::array::{ArrayRef, Int32Array};
123    use crate::{ArrayIterator, ArrayReader};
124
125    fn test_field() -> Arc<Field> {
126        Arc::new(Field::new("values", DataType::Int32, true))
127    }
128
129    #[test]
130    fn array_iterator_reports_its_field_and_yields_its_arrays() {
131        let field = test_field();
132        let a: ArrayRef = Arc::new(Int32Array::from(vec![1, 2]));
133        let b: ArrayRef = Arc::new(Int32Array::from(vec![3]));
134
135        let mut reader = ArrayIterator::new(
136            vec![a.clone(), b.clone()].into_iter().map(Ok),
137            field.clone(),
138        );
139
140        assert_eq!(reader.field(), &field);
141        assert_eq!(&reader.next().unwrap().unwrap(), &a);
142        assert_eq!(&reader.next().unwrap().unwrap(), &b);
143        assert!(reader.next().is_none());
144    }
145
146    #[test]
147    fn array_iterator_delegates_size_hint() {
148        let arrays: Vec<Result<ArrayRef, ArrowError>> =
149            vec![Ok(Arc::new(Int32Array::from(vec![1])) as ArrayRef)];
150        let reader = ArrayIterator::new(arrays, test_field());
151
152        assert_eq!(reader.size_hint(), (1, Some(1)));
153    }
154
155    #[test]
156    fn boxed_array_reader_forwards_field() {
157        let field = test_field();
158        let reader = ArrayIterator::new(std::iter::empty(), field.clone());
159
160        let boxed: Box<dyn ArrayReader + Send> = Box::new(reader);
161        assert_eq!(boxed.field(), &field);
162    }
163}