1use vortex_error::VortexResult;
5use vortex_error::vortex_bail;
6use vortex_mask::Mask;
7
8use crate::ArrayRef;
9use crate::Executable;
10use crate::ExecutionCtx;
11use crate::IntoArray;
12use crate::arrays::BoolArray;
13use crate::builtins::ArrayBuiltins;
14use crate::columnar::Columnar;
15use crate::dtype::DType;
16use crate::dtype::Nullability;
17
18impl Executable for Mask {
19 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
25 if !matches!(array.dtype(), DType::Bool(Nullability::NonNullable)) {
26 vortex_bail!(
27 "Mask array must have boolean(NonNullable) dtype, not {}",
28 array.dtype()
29 );
30 }
31
32 let array_len = array.len();
33 Ok(match array.execute(ctx)? {
34 Columnar::Constant(s) => {
35 Mask::new(array_len, s.scalar().as_bool().value().unwrap_or(false))
36 }
37 Columnar::Canonical(a) => {
38 let bool = a.into_array().execute::<BoolArray>(ctx)?;
39 Mask::from(bool.into_bit_buffer())
40 }
41 })
42 }
43}
44
45#[deprecated = "Use array.fill_null(false)?.execute::<Mask>(ctx)"]
46pub struct NullAsFalse(ArrayRef);
47impl ArrayRef {
48 #[deprecated = "Use array.fill_null(false)?.execute::<Mask>(ctx)"]
49 #[allow(deprecated)]
50 pub fn null_as_false(self) -> NullAsFalse {
51 NullAsFalse(self)
52 }
53}
54#[allow(deprecated)]
55impl NullAsFalse {
56 #[deprecated = "Use array.fill_null(false)?.execute::<Mask>(ctx)"]
57 pub fn execute(self, ctx: &mut ExecutionCtx) -> VortexResult<Mask> {
58 self.0.fill_null(false)?.execute::<Mask>(ctx)
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use vortex_error::VortexResult;
65 use vortex_mask::Mask;
66
67 use crate::ExecutionCtx;
68 use crate::IntoArray;
69 use crate::VortexSessionExecute;
70 use crate::array_session;
71 use crate::arrays::BoolArray;
72 use crate::arrays::ConstantArray;
73 use crate::builtins::ArrayBuiltins;
74 use crate::dtype::DType;
75 use crate::dtype::Nullability;
76 use crate::scalar::Scalar;
77
78 fn ctx() -> ExecutionCtx {
79 array_session().create_execution_ctx()
80 }
81
82 #[test]
83 fn mask_non_nullable() -> VortexResult<()> {
84 let array = BoolArray::from_iter([true, false, true]).into_array();
85 let mask = array.execute::<Mask>(&mut ctx())?;
86 assert_eq!(mask, Mask::from_iter([true, false, true]));
87 Ok(())
88 }
89
90 #[test]
91 fn mask_rejects_nullable() {
92 let array = BoolArray::from_iter([Some(true), None]).into_array();
93 assert!(array.execute::<Mask>(&mut ctx()).is_err());
94 }
95
96 #[test]
97 fn fill_null_then_mask_coerces_nulls() -> VortexResult<()> {
98 let array = BoolArray::from_iter([Some(true), None, Some(false), None]).into_array();
99 let mask = array.fill_null(false)?.execute::<Mask>(&mut ctx())?;
100 assert_eq!(mask, Mask::from_iter([true, false, false, false]));
101 Ok(())
102 }
103
104 #[test]
105 fn fill_null_then_mask_null_constant() -> VortexResult<()> {
106 let array =
107 ConstantArray::new(Scalar::null(DType::Bool(Nullability::Nullable)), 4).into_array();
108 let mask = array.fill_null(false)?.execute::<Mask>(&mut ctx())?;
109 assert_eq!(mask, Mask::new_false(4));
110 Ok(())
111 }
112}