vortex_array/arrays/masked/
array.rs1use std::fmt::Display;
5use std::fmt::Formatter;
6
7use smallvec::smallvec;
8use vortex_error::VortexResult;
9use vortex_error::vortex_bail;
10
11use crate::ArrayRef;
12use crate::VortexSessionExecute;
13use crate::array::Array;
14use crate::array::ArrayParts;
15use crate::array::TypedArrayRef;
16use crate::array::child_to_validity;
17use crate::array::validity_to_child;
18use crate::array_slots;
19use crate::arrays::Masked;
20use crate::legacy_session;
21use crate::validity::Validity;
22
23#[array_slots(Masked)]
24pub struct MaskedSlots {
25 #[slot(0)]
27 pub child: ArrayRef,
28 #[slot(1)]
30 pub validity: Option<ArrayRef>,
31}
32
33#[derive(Clone, Debug)]
34pub struct MaskedData;
35
36impl Display for MaskedData {
37 fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
38 Ok(())
39 }
40}
41
42pub trait MaskedArrayExt: TypedArrayRef<Masked> + MaskedArraySlotsExt {
43 fn masked_validity(&self) -> Validity {
44 child_to_validity(
45 self.as_ref().slots()[MaskedSlots::VALIDITY].as_ref(),
46 self.as_ref().dtype().nullability(),
47 )
48 }
49}
50impl<T: TypedArrayRef<Masked>> MaskedArrayExt for T {}
51
52impl MaskedData {
53 pub(crate) fn try_new(
54 child_len: usize,
55 child_all_valid: bool,
56 validity: Validity,
57 ) -> VortexResult<Self> {
58 if matches!(validity, Validity::NonNullable) {
59 vortex_bail!("MaskedArray must have nullable validity, got {validity:?}")
60 }
61
62 if !child_all_valid {
63 vortex_bail!("MaskedArray children must not have nulls");
64 }
65
66 if let Some(validity_len) = validity.maybe_len()
67 && validity_len != child_len
68 {
69 vortex_bail!("Validity must be the same length as a MaskedArray's child");
70 }
71
72 Ok(Self)
75 }
76}
77
78impl Array<Masked> {
79 #[allow(clippy::disallowed_methods)]
81 pub fn try_new(child: ArrayRef, validity: Validity) -> VortexResult<Self> {
82 let dtype = child.dtype().as_nullable();
83 let len = child.len();
84 let validity_slot = validity_to_child(&validity, len);
85 let data = MaskedData::try_new(
86 len,
87 child.all_valid(&mut legacy_session().create_execution_ctx())?,
88 validity,
89 )?;
90 Ok(unsafe {
91 Array::from_parts_unchecked(
92 ArrayParts::new(Masked, dtype, len, data)
93 .with_slots(smallvec![Some(child), validity_slot]),
94 )
95 })
96 }
97}