Skip to main content

arrow/
lib.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//! A complete, safe, native Rust implementation of [Apache Arrow](https://arrow.apache.org), a cross-language
19//! development platform for in-memory data.
20//!
21//! Please see the [arrow crates.io](https://crates.io/crates/arrow)
22//! page for feature flags and tips to improve performance.
23//!
24//! # Platform Support
25//!
26//! Only little-endian platforms are officially supported and tested in CI.
27//! Big-endian platforms are not tested in CI and may not work correctly.
28//! Fixes for big-endian platforms are welcome and handled on a best-effort basis,
29//! but compatibility is not guaranteed.
30//!
31//! # Columnar Format
32//!
33//! The [`array`] module provides statically typed implementations of all the array types as defined
34//! by the [Arrow Columnar Format](https://arrow.apache.org/docs/format/Columnar.html)
35//!
36//! For example, an [`Int32Array`](array::Int32Array) represents a nullable array of `i32`
37//!
38//! ```rust
39//! # use arrow::array::{Array, Int32Array};
40//! let array = Int32Array::from(vec![Some(1), None, Some(3)]);
41//! assert_eq!(array.len(), 3);
42//! assert_eq!(array.value(0), 1);
43//! assert_eq!(array.is_null(1), true);
44//!
45//! let collected: Vec<_> = array.iter().collect();
46//! assert_eq!(collected, vec![Some(1), None, Some(3)]);
47//! assert_eq!(array.values(), &[1, 0, 3])
48//! ```
49//!
50//! It is also possible to write generic code for different concrete types.
51//! For example, since the following function is generic over all primitively
52//! typed arrays, when invoked the Rust compiler will generate specialized implementations
53//! with optimized code for each concrete type.
54//!
55//! ```rust
56//! # use std::iter::Sum;
57//! # use arrow::array::{Float32Array, PrimitiveArray, TimestampNanosecondArray};
58//! # use arrow::datatypes::ArrowPrimitiveType;
59//! #
60//! fn sum<T: ArrowPrimitiveType>(array: &PrimitiveArray<T>) -> T::Native
61//! where
62//!     T: ArrowPrimitiveType,
63//!     T::Native: Sum
64//! {
65//!     array.iter().map(|v| v.unwrap_or_default()).sum()
66//! }
67//!
68//! assert_eq!(sum(&Float32Array::from(vec![1.1, 2.9, 3.])), 7.);
69//! assert_eq!(sum(&TimestampNanosecondArray::from(vec![1, 2, 3])), 6);
70//! ```
71//!
72//! And the following uses [`ArrayAccessor`] to implement a generic function
73//! over all arrays with comparable values.
74//!
75//! [`ArrayAccessor`]: array::ArrayAccessor
76//!
77//! ```rust
78//! # use arrow::array::{ArrayAccessor, ArrayIter, Int32Array, StringArray};
79//! # use arrow::datatypes::ArrowPrimitiveType;
80//! #
81//! fn min<T: ArrayAccessor>(array: T) -> Option<T::Item>
82//! where
83//!     T::Item: Ord
84//! {
85//!     ArrayIter::new(array).filter_map(|v| v).min()
86//! }
87//!
88//! assert_eq!(min(&Int32Array::from(vec![4, 2, 1, 6])), Some(1));
89//! assert_eq!(min(&StringArray::from(vec!["b", "a", "c"])), Some("a"));
90//! ```
91//!
92//! **For more examples, and details consult the [arrow_array] docs.**
93//!
94//! # Type Erasure / Trait Objects
95//!
96//! It is common to write code that handles any type of array, without necessarily
97//! knowing its concrete type. This is done using the [`Array`] trait and using
98//! [`DataType`] to determine the appropriate `downcast_ref`.
99//!
100//! [`DataType`]: datatypes::DataType
101//!
102//! ```rust
103//! # use arrow::array::{Array, Float32Array};
104//! # use arrow::array::StringArray;
105//! # use arrow::datatypes::DataType;
106//! #
107//! fn impl_string(array: &StringArray) {}
108//! fn impl_f32(array: &Float32Array) {}
109//!
110//! fn impl_dyn(array: &dyn Array) {
111//!     match array.data_type() {
112//!         // downcast `dyn Array` to concrete `StringArray`
113//!         DataType::Utf8 => impl_string(array.as_any().downcast_ref().unwrap()),
114//!         // downcast `dyn Array` to concrete `Float32Array`
115//!         DataType::Float32 => impl_f32(array.as_any().downcast_ref().unwrap()),
116//!         _ => unimplemented!()
117//!     }
118//! }
119//! ```
120//!
121//! You can use the [`AsArray`] extension trait to facilitate downcasting:
122//!
123//! [`AsArray`]: crate::array::AsArray
124//!
125//! ```rust
126//! # use arrow::array::{Array, Float32Array, AsArray};
127//! # use arrow::array::StringArray;
128//! # use arrow::datatypes::DataType;
129//! #
130//! fn impl_string(array: &StringArray) {}
131//! fn impl_f32(array: &Float32Array) {}
132//!
133//! fn impl_dyn(array: &dyn Array) {
134//!     match array.data_type() {
135//!         DataType::Utf8 => impl_string(array.as_string()),
136//!         DataType::Float32 => impl_f32(array.as_primitive()),
137//!         _ => unimplemented!()
138//!     }
139//! }
140//! ```
141//!
142//! It is also common to want to write a function that returns one of a number of possible
143//! array implementations. [`ArrayRef`] is a type-alias for [`Arc<dyn Array>`](array::Array)
144//! which is frequently used for this purpose
145//!
146//! ```rust
147//! # use std::str::FromStr;
148//! # use std::sync::Arc;
149//! # use arrow::array::{ArrayRef, Int32Array, PrimitiveArray};
150//! # use arrow::datatypes::{ArrowPrimitiveType, DataType, Int32Type, UInt32Type};
151//! # use arrow::compute::cast;
152//! #
153//! fn parse_to_primitive<'a, T, I>(iter: I) -> PrimitiveArray<T>
154//! where
155//!     T: ArrowPrimitiveType,
156//!     T::Native: FromStr,
157//!     I: IntoIterator<Item=&'a str>,
158//! {
159//!     PrimitiveArray::from_iter(iter.into_iter().map(|val| T::Native::from_str(val).ok()))
160//! }
161//!
162//! fn parse_strings<'a, I>(iter: I, to_data_type: DataType) -> ArrayRef
163//! where
164//!     I: IntoIterator<Item=&'a str>,
165//! {
166//!    match to_data_type {
167//!        DataType::Int32 => Arc::new(parse_to_primitive::<Int32Type, _>(iter)) as _,
168//!        DataType::UInt32 => Arc::new(parse_to_primitive::<UInt32Type, _>(iter)) as _,
169//!        _ => unimplemented!()
170//!    }
171//! }
172//!
173//! let array = parse_strings(["1", "2", "3"], DataType::Int32);
174//! let integers = array.as_any().downcast_ref::<Int32Array>().unwrap();
175//! assert_eq!(integers.values(), &[1, 2, 3])
176//! ```
177//!
178//! # Compute Kernels
179//!
180//! The [`compute`] module provides optimised implementations of many common operations,
181//! for example the `parse_strings` operation above could also be implemented as follows:
182//!
183//! ```
184//! # use std::sync::Arc;
185//! # use arrow::error::Result;
186//! # use arrow::array::{ArrayRef, StringArray, UInt32Array};
187//! # use arrow::datatypes::DataType;
188//! #
189//! fn parse_strings<'a, I>(iter: I, to_data_type: &DataType) -> Result<ArrayRef>
190//! where
191//!     I: IntoIterator<Item=&'a str>,
192//! {
193//!     let array = StringArray::from_iter(iter.into_iter().map(Some));
194//!     arrow::compute::cast(&array, to_data_type)
195//! }
196//!
197//! let array = parse_strings(["1", "2", "3"], &DataType::UInt32).unwrap();
198//! let integers = array.as_any().downcast_ref::<UInt32Array>().unwrap();
199//! assert_eq!(integers.values(), &[1, 2, 3])
200//! ```
201//!
202//! This module also implements many common vertical operations:
203//!
204//! * All mathematical binary operators, such as [`sub`](compute::kernels::numeric::sub)
205//! * All boolean binary operators such as [`equality`](compute::kernels::cmp::eq)
206//! * [`cast`](compute::kernels::cast::cast)
207//! * [`filter`](compute::kernels::filter::filter)
208//! * [`take`](compute::kernels::take::take)
209//! * [`sort`](compute::kernels::sort::sort)
210//! * some string operators such as [`substring`](compute::kernels::substring::substring) and [`length`](compute::kernels::length::length)
211//!
212//! ```
213//! # use arrow::compute::kernels::cmp::gt;
214//! # use arrow_array::cast::AsArray;
215//! # use arrow_array::Int32Array;
216//! # use arrow_array::types::Int32Type;
217//! # use arrow_select::filter::filter;
218//! let array = Int32Array::from_iter(0..100);
219//! // Create a 32-bit integer scalar (single) value:
220//! let scalar = Int32Array::new_scalar(60);
221//! // find all rows in the array that are greater than 60
222//! let predicate = gt(&array, &scalar).unwrap();
223//! // copy all matching rows into a new array
224//! let filtered = filter(&array, &predicate).unwrap();
225//!
226//! let expected = Int32Array::from_iter(61..100);
227//! assert_eq!(&expected, filtered.as_primitive::<Int32Type>());
228//! ```
229//!
230//! As well as some horizontal operations, such as:
231//!
232//! * [`min`](compute::kernels::aggregate::min) and [`max`](compute::kernels::aggregate::max)
233//! * [`sum`](compute::kernels::aggregate::sum)
234//!
235//! # Tabular Representation
236//!
237//! It is common to want to group one or more columns together into a tabular representation. This
238//! is provided by [`RecordBatch`] which combines a [`Schema`](datatypes::Schema)
239//! and a corresponding list of [`ArrayRef`].
240//!
241//!
242//! ```
243//! # use std::sync::Arc;
244//! # use arrow::array::{Float32Array, Int32Array};
245//! # use arrow::record_batch::RecordBatch;
246//! #
247//! let col_1 = Arc::new(Int32Array::from_iter([1, 2, 3])) as _;
248//! let col_2 = Arc::new(Float32Array::from_iter([1., 6.3, 4.])) as _;
249//!
250//! let batch = RecordBatch::try_from_iter([("col1", col_1), ("col_2", col_2)]).unwrap();
251//! ```
252//!
253//! # Pretty Printing
254//!
255//! See the [`util::pretty`] module (requires the `prettyprint` crate feature)
256//!
257//! # IO
258//!
259//! This crate provides readers and writers for various formats to/from [`RecordBatch`]
260//!
261//! * JSON: [`Reader`](json::reader::Reader) and [`Writer`](json::writer::Writer)
262//! * CSV: [`Reader`](csv::reader::Reader) and [`Writer`](csv::writer::Writer)
263//! * IPC: [`Reader`](ipc::reader::StreamReader) and [`Writer`](ipc::writer::FileWriter)
264//!
265//! Support for [Apache Parquet] is published as a [separate parquet crate](https://crates.io/crates/parquet)
266//!
267//! Support for [Apache Avro] is published as a [separate arrow-avro crate](https://crates.io/crates/arrow-avro)
268//!
269//! # Serde Compatibility
270//!
271//! [`arrow_json::reader::Decoder`] provides a mechanism to convert arbitrary, serde-compatible
272//! structures into [`RecordBatch`].
273//!
274//! Whilst likely less performant than implementing a custom builder, as described in
275//! [arrow_array::builder], this provides a simple mechanism to get up and running quickly
276//!
277//! ```
278//! # use std::sync::Arc;
279//! # use arrow_json::ReaderBuilder;
280//! # use arrow_schema::{DataType, Field, Schema};
281//! # use serde::Serialize;
282//! # use arrow_array::cast::AsArray;
283//! # use arrow_array::types::{Float32Type, Int32Type};
284//! #
285//! #[derive(Serialize)]
286//! struct MyStruct {
287//!     int32: i32,
288//!     string: String,
289//! }
290//!
291//! let schema = Schema::new(vec![
292//!     Field::new("int32", DataType::Int32, false),
293//!     Field::new("string", DataType::Utf8, false),
294//! ]);
295//!
296//! let rows = vec![
297//!     MyStruct{ int32: 5, string: "bar".to_string() },
298//!     MyStruct{ int32: 8, string: "foo".to_string() },
299//! ];
300//!
301//! let mut decoder = ReaderBuilder::new(Arc::new(schema)).build_decoder().unwrap();
302//! decoder.serialize(&rows).unwrap();
303//!
304//! let batch = decoder.flush().unwrap().unwrap();
305//!
306//! // Expect batch containing two columns
307//! let int32 = batch.column(0).as_primitive::<Int32Type>();
308//! assert_eq!(int32.values(), &[5, 8]);
309//!
310//! let string = batch.column(1).as_string::<i32>();
311//! assert_eq!(string.value(0), "bar");
312//! assert_eq!(string.value(1), "foo");
313//! ```
314//!
315//! # Crate Topology
316//!
317//! The [`arrow`] project is implemented as multiple sub-crates, which are then re-exported by
318//! this top-level crate.
319//!
320//! Crate authors can choose to depend on this top-level crate, or just
321//! the sub-crates they need.
322//!
323//! The current list of sub-crates is:
324//!
325//! * [`arrow-arith`][arrow_arith] - arithmetic kernels
326//! * [`arrow-array`][arrow_array] - type-safe arrow array abstractions
327//! * [`arrow-buffer`][arrow_buffer] - buffer abstractions for arrow arrays
328//! * [`arrow-cast`][arrow_cast] - cast kernels for arrow arrays
329//! * [`arrow-csv`][arrow_csv] - read/write CSV to arrow format
330//! * [`arrow-data`][arrow_data] - the underlying data of arrow arrays
331//! * [`arrow-ipc`][arrow_ipc] - read/write IPC to arrow format
332//! * [`arrow-json`][arrow_json] - read/write JSON to arrow format
333//! * [`arrow-ord`][arrow_ord] - ordering kernels for arrow arrays
334//! * [`arrow-row`][arrow_row] - comparable row format
335//! * [`arrow-schema`][arrow_schema] - the logical types for arrow arrays
336//! * [`arrow-select`][arrow_select] - selection kernels for arrow arrays
337//! * [`arrow-string`][arrow_string] - string kernels for arrow arrays
338//!
339//! Some functionality is also distributed independently of this crate:
340//!
341//! * [`arrow-flight`] - support for [Arrow Flight RPC]
342//! * [`parquet`](https://docs.rs/parquet) - support for [Apache Parquet]
343//! * [`arrow-avro`](https://docs.rs/arrow-avro) - support for [Apache Avro]
344//!
345//! # Security
346//!
347//! This project follows the [Apache Arrow Security Model].
348//!
349//! Unexpected behavior (e.g., panics, crashes, or infinite loops) triggered by
350//! malformed input is considered a **bug**, not a security vulnerability,
351//! unless it is **exploitable** by an attacker to
352//!
353//! * Execute arbitrary code (Remote Code Execution);
354//! * Exfiltrate sensitive information from process memory (Information Disclosure);
355//!
356//! If you think you have found a security vulnerability, please follow the
357//! reporting instructions in the [security policy].
358//!
359//! [security policy]: https://github.com/apache/arrow-rs/blob/main/SECURITY.md
360//!
361//! # Safety
362//!
363//! Like many crates, this crate makes use of `unsafe` where prudent. However, it endeavors to be
364//! sound. Specifically, **it should not be possible to trigger undefined behavior using safe APIs.**
365//!
366//! Undefined behavior using safe APIs is considered a bug, not a security
367//! vulnerability, unless it can be exploited. Please see the [security policy]
368//! for details.
369//!
370//! For more information on the use of `unsafe`, see [here](https://github.com/apache/arrow-rs/tree/main/arrow#safety).
371//!
372//! [Apache Arrow Security Model]: https://arrow.apache.org/docs/dev/format/Security.html
373//!
374//! # Higher-level Processing
375//!
376//! This crate aims to provide reusable, low-level primitives for operating on columnar data. For
377//! more sophisticated query processing workloads, consider checking out [DataFusion]. This
378//! orchestrates the primitives exported by this crate into an embeddable query engine, with
379//! SQL and DataFrame frontends, and heavily influences this crate's roadmap.
380//!
381//! [`arrow`]: https://github.com/apache/arrow-rs
382//! [`array`]: mod@array
383//! [`Array`]: array::Array
384//! [`ArrayRef`]: array::ArrayRef
385//! [`ArrayData`]: array::ArrayData
386//! [`make_array`]: array::make_array
387//! [`Buffer`]: buffer::Buffer
388//! [`RecordBatch`]: record_batch::RecordBatch
389//! [`arrow-flight`]: https://docs.rs/arrow-flight/latest/arrow_flight/
390//! [`parquet`]: https://docs.rs/parquet/latest/parquet/
391//! [Arrow Flight RPC]: https://arrow.apache.org/docs/format/Flight.html
392//! [Arrow JSON Test Format]: https://github.com/apache/arrow/blob/master/docs/source/format/Integration.rst#json-test-data-format
393//! [Apache Parquet]: https://parquet.apache.org/
394//! [Apache Avro]: https://avro.apache.org/
395//! [DataFusion]: https://github.com/apache/arrow-datafusion
396//! [issue tracker]: https://github.com/apache/arrow-rs/issues
397
398#![doc(
399    html_logo_url = "https://arrow.apache.org/img/arrow-logo_chevrons_black-txt_white-bg.svg",
400    html_favicon_url = "https://arrow.apache.org/img/arrow-logo_chevrons_black-txt_transparent-bg.svg"
401)]
402#![cfg_attr(docsrs, feature(doc_cfg))]
403#![deny(clippy::redundant_clone)]
404#![warn(missing_debug_implementations)]
405#![warn(missing_docs)]
406#![allow(rustdoc::invalid_html_tags)]
407pub use arrow_array::{downcast_dictionary_array, downcast_primitive_array};
408
409pub use arrow_buffer::{alloc, buffer};
410
411/// Arrow crate version
412pub const ARROW_VERSION: &str = env!("CARGO_PKG_VERSION");
413
414pub mod array;
415pub mod compute;
416#[cfg(feature = "csv")]
417pub use arrow_csv as csv;
418pub mod datatypes;
419pub mod error;
420#[cfg(feature = "ffi")]
421pub use arrow_array::ffi;
422#[cfg(feature = "ffi")]
423pub use arrow_array::ffi_stream;
424#[cfg(feature = "ipc")]
425pub use arrow_ipc as ipc;
426#[cfg(feature = "json")]
427pub use arrow_json as json;
428#[cfg(feature = "pyarrow")]
429pub use arrow_pyarrow as pyarrow;
430
431/// Contains the `RecordBatch` type and associated traits
432pub mod record_batch {
433    pub use arrow_array::{
434        RecordBatch, RecordBatchIterator, RecordBatchOptions, RecordBatchReader, RecordBatchWriter,
435    };
436}
437pub use arrow_array::temporal_conversions;
438pub use arrow_row as row;
439pub mod tensor;
440pub mod util;