diff --git a/Cargo.lock b/Cargo.lock index dfffe28c..5f4536ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "const-random", diff --git a/src/array/null.rs b/src/array/null.rs index 7259d2a2..2dda86da 100644 --- a/src/array/null.rs +++ b/src/array/null.rs @@ -39,7 +39,7 @@ unsafe impl Unit for () { /// A sequence of nulls. pub struct NullArray( - pub as Validity>::Storage, + pub(crate) as Validity>::Storage, ) where Nulls: Validity; @@ -182,6 +182,17 @@ pub struct Nulls { _ty: PhantomData T>, } +impl Nulls { + #[cfg(feature = "arrow-rs")] + /// Constructs a Nulls from a given length. + pub(crate) fn new(len: usize) -> Self { + Self { + len, + _ty: PhantomData, + } + } +} + impl FromIterator for Nulls { fn from_iter>(iter: I) -> Self { Self { diff --git a/src/arrow/array/mod.rs b/src/arrow/array/mod.rs index be7cb644..6ab05af4 100644 --- a/src/arrow/array/mod.rs +++ b/src/arrow/array/mod.rs @@ -7,4 +7,5 @@ mod string; mod r#struct; pub use r#struct::StructArrayTypeFields; mod logical; +mod null; mod variable_size_list; diff --git a/src/arrow/array/null.rs b/src/arrow/array/null.rs new file mode 100644 index 00000000..6e6d34d0 --- /dev/null +++ b/src/arrow/array/null.rs @@ -0,0 +1,86 @@ +//! Interop with `arrow-rs` boolean array. + +use std::sync::Arc; + +use crate::{ + array::{NullArray, Nulls, Unit}, + arrow::ArrowArray, + buffer::BufferType, + validity::{Nullability, Validity}, + Length, +}; +use arrow_array::Array; +use arrow_schema::{DataType, Field}; + +impl ArrowArray + for NullArray +where + T: Nullability, + Nulls: Validity, +{ + type Array = arrow_array::NullArray; + + fn as_field(name: &str) -> arrow_schema::Field { + Field::new(name, DataType::Null, NULLABLE) + } +} + +impl From> for NullArray +where + Self: From, +{ + fn from(value: Arc) -> Self { + Self::from(arrow_array::NullArray::from(value.to_data())) + } +} + +impl From> for arrow_array::NullArray { + fn from(value: NullArray) -> Self { + arrow_array::NullArray::new(value.len()) + } +} + +/// Panics when there are nulls +impl From for NullArray { + fn from(value: arrow_array::NullArray) -> Self { + NullArray(Nulls::new(value.len())) + } +} + +#[cfg(test)] +mod tests { + use crate::{array::NullArray, buffer::ArcBuffer, Length}; + use arrow_array::Array; + + const INPUT: [(); 4] = [(), (), (), ()]; + + #[test] + fn from() { + let null_array = INPUT.into_iter().collect::(); + assert_eq!( + arrow_array::NullArray::new(null_array.len()).len(), + INPUT.len() + ); + + let null_array_arc = INPUT + .into_iter() + .collect::>(); + assert_eq!( + arrow_array::NullArray::new(null_array_arc.len()).len(), + INPUT.len() + ); + } + + #[test] + fn into() { + let null_array = arrow_array::NullArray::new(INPUT.len()); + assert_eq!( + NullArray::<(), false, crate::arrow::buffer::scalar_buffer::ArrowScalarBuffer>::from( + null_array + ) + .into_iter() + .collect::>(), + INPUT + ); + } +}