vortex_array/arrays/bool/compute/
fill_null.rs1use vortex_error::{VortexResult, vortex_err};
5use vortex_scalar::Scalar;
6
7use crate::arrays::{BoolArray, BoolVTable};
8use crate::compute::{FillNullKernel, FillNullKernelAdapter};
9use crate::validity::Validity;
10use crate::vtable::ValidityHelper;
11use crate::{ArrayRef, IntoArray, ToCanonical, register_kernel};
12
13impl FillNullKernel for BoolVTable {
14 fn fill_null(&self, array: &BoolArray, fill_value: &Scalar) -> VortexResult<ArrayRef> {
15 let fill = fill_value
16 .as_bool()
17 .value()
18 .ok_or_else(|| vortex_err!("Fill value must be non null"))?;
19
20 Ok(match array.validity() {
21 Validity::Array(v) => {
22 let bool_buffer = if fill {
23 array.bit_buffer() | &!v.to_bool().bit_buffer()
24 } else {
25 array.bit_buffer() & v.to_bool().bit_buffer()
26 };
27 BoolArray::from_bit_buffer(bool_buffer, fill_value.dtype().nullability().into())
28 .into_array()
29 }
30 _ => unreachable!("checked in entry point"),
31 })
32 }
33}
34
35register_kernel!(FillNullKernelAdapter(BoolVTable).lift());
36
37#[cfg(test)]
38mod tests {
39 use rstest::rstest;
40 use vortex_buffer::{BitBuffer, bitbuffer};
41 use vortex_dtype::{DType, Nullability};
42
43 use crate::arrays::BoolArray;
44 use crate::canonical::ToCanonical;
45 use crate::compute::fill_null;
46 use crate::validity::Validity;
47
48 #[rstest]
49 #[case(true, bitbuffer![true, true, false, true])]
50 #[case(false, bitbuffer![true, false, false, false])]
51 fn bool_fill_null(#[case] fill_value: bool, #[case] expected: BitBuffer) {
52 let bool_array = BoolArray::from_bit_buffer(
53 BitBuffer::from_iter([true, true, false, false]),
54 Validity::from_iter([true, false, true, false]),
55 );
56 let non_null_array = fill_null(bool_array.as_ref(), &fill_value.into())
57 .unwrap()
58 .to_bool();
59 assert_eq!(non_null_array.bit_buffer(), &expected);
60 assert_eq!(
61 non_null_array.dtype(),
62 &DType::Bool(Nullability::NonNullable)
63 );
64 }
65}