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