Skip to content

Commit

Permalink
feat: add arrow NullArray interop (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbrobbel authored Feb 6, 2024
1 parent 3927d2c commit 02c54a7
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 3 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion src/array/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ unsafe impl Unit for () {

/// A sequence of nulls.
pub struct NullArray<T: Unit = (), const NULLABLE: bool = false, Buffer: BufferType = VecBuffer>(
pub <Nulls<T> as Validity<NULLABLE>>::Storage<Buffer>,
pub(crate) <Nulls<T> as Validity<NULLABLE>>::Storage<Buffer>,
)
where
Nulls<T>: Validity<NULLABLE>;
Expand Down Expand Up @@ -182,6 +182,17 @@ pub struct Nulls<T: Unit> {
_ty: PhantomData<fn() -> T>,
}

impl<T: Unit> Nulls<T> {
#[cfg(feature = "arrow-rs")]
/// Constructs a Nulls from a given length.
pub(crate) fn new(len: usize) -> Self {
Self {
len,
_ty: PhantomData,
}
}
}

impl<T: Unit> FromIterator<T> for Nulls<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self {
Expand Down
1 change: 1 addition & 0 deletions src/arrow/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ mod string;
mod r#struct;
pub use r#struct::StructArrayTypeFields;
mod logical;
mod null;
mod variable_size_list;
86 changes: 86 additions & 0 deletions src/arrow/array/null.rs
Original file line number Diff line number Diff line change
@@ -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<T: Unit, const NULLABLE: bool, Buffer: BufferType> ArrowArray
for NullArray<T, NULLABLE, Buffer>
where
T: Nullability<NULLABLE>,
Nulls<T>: Validity<NULLABLE>,
{
type Array = arrow_array::NullArray;

fn as_field(name: &str) -> arrow_schema::Field {
Field::new(name, DataType::Null, NULLABLE)
}
}

impl<T: Unit, Buffer: BufferType> From<Arc<dyn arrow_array::Array>> for NullArray<T, false, Buffer>
where
Self: From<arrow_array::NullArray>,
{
fn from(value: Arc<dyn arrow_array::Array>) -> Self {
Self::from(arrow_array::NullArray::from(value.to_data()))
}
}

impl<T: Unit, Buffer: BufferType> From<NullArray<T, false, Buffer>> for arrow_array::NullArray {
fn from(value: NullArray<T, false, Buffer>) -> Self {
arrow_array::NullArray::new(value.len())
}
}

/// Panics when there are nulls
impl<T: Unit, Buffer: BufferType> From<arrow_array::NullArray> for NullArray<T, false, Buffer> {
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::<NullArray>();
assert_eq!(
arrow_array::NullArray::new(null_array.len()).len(),
INPUT.len()
);

let null_array_arc = INPUT
.into_iter()
.collect::<NullArray<_, false, ArcBuffer>>();
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::<Vec<_>>(),
INPUT
);
}
}

0 comments on commit 02c54a7

Please sign in to comment.