vortex_vector/bool/
vector.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! Definition and implementation of [`BoolVector`].
5
6use std::fmt::Debug;
7use std::ops::BitAnd;
8use std::ops::RangeBounds;
9
10use vortex_buffer::BitBuffer;
11use vortex_error::VortexExpect;
12use vortex_error::VortexResult;
13use vortex_error::vortex_ensure;
14use vortex_mask::Mask;
15
16use crate::VectorOps;
17use crate::bool::BoolScalar;
18use crate::bool::BoolVectorMut;
19
20/// An immutable vector of boolean values.
21///
22/// Internally, this `BoolVector` is a wrapper around a [`BitBuffer`] and a validity mask.
23#[derive(Debug, Clone)]
24pub struct BoolVector {
25    /// The bits that we use to represent booleans.
26    pub(super) bits: BitBuffer,
27    /// The validity mask (where `true` represents an element is **not** null).
28    pub(super) validity: Mask,
29}
30
31impl BoolVector {
32    /// Creates a new [`BoolVector`] from the given bits and validity mask.
33    ///
34    /// # Panics
35    ///
36    /// Panics if the length of the validity mask does not match the length of the bits.
37    pub fn new(bits: BitBuffer, validity: Mask) -> Self {
38        Self::try_new(bits, validity).vortex_expect("Failed to create `BoolVector`")
39    }
40
41    /// Tries to create a new [`BoolVector`] from the given bits and validity mask.
42    ///
43    /// # Errors
44    ///
45    /// Returns an error if the length of the validity mask does not match the length of the bits.
46    pub fn try_new(bits: BitBuffer, validity: Mask) -> VortexResult<Self> {
47        vortex_ensure!(
48            validity.len() == bits.len(),
49            "`BoolVector` validity mask must have the same length as bits"
50        );
51
52        Ok(Self { bits, validity })
53    }
54
55    /// Creates a new [`BoolVector`] from the given bits and validity mask without validation.
56    ///
57    /// # Safety
58    ///
59    /// The caller must ensure that the validity mask has the same length as the bits.
60    pub unsafe fn new_unchecked(bits: BitBuffer, validity: Mask) -> Self {
61        if cfg!(debug_assertions) {
62            Self::new(bits, validity)
63        } else {
64            Self { bits, validity }
65        }
66    }
67
68    /// Decomposes the boolean vector into its constituent parts (bit buffer and validity).
69    pub fn into_parts(self) -> (BitBuffer, Mask) {
70        (self.bits, self.validity)
71    }
72
73    /// Returns the bits buffer of the boolean vector.
74    pub fn bits(&self) -> &BitBuffer {
75        &self.bits
76    }
77
78    /// Returns the bits buffer of the boolean vector.
79    pub fn into_bits(self) -> BitBuffer {
80        self.bits
81    }
82}
83
84impl VectorOps for BoolVector {
85    type Mutable = BoolVectorMut;
86    type Scalar = BoolScalar;
87
88    fn len(&self) -> usize {
89        debug_assert!(self.validity.len() == self.bits.len());
90        self.bits.len()
91    }
92
93    fn validity(&self) -> &Mask {
94        &self.validity
95    }
96
97    fn mask_validity(&mut self, mask: &Mask) {
98        self.validity = self.validity.bitand(mask);
99    }
100
101    fn scalar_at(&self, index: usize) -> BoolScalar {
102        assert!(index < self.len());
103
104        let is_valid = self.validity.value(index);
105        let value = is_valid.then(|| self.bits.value(index));
106
107        BoolScalar::new(value)
108    }
109
110    fn slice(&self, range: impl RangeBounds<usize> + Clone + Debug) -> Self {
111        let bits = self.bits.slice(range.clone());
112        let validity = self.validity.slice(range);
113        Self { bits, validity }
114    }
115
116    fn clear(&mut self) {
117        self.bits.clear();
118        self.validity.clear();
119    }
120
121    fn try_into_mut(self) -> Result<BoolVectorMut, Self> {
122        let bits = match self.bits.try_into_mut() {
123            Ok(bits) => bits,
124            Err(bits) => {
125                return Err(Self {
126                    bits,
127                    validity: self.validity,
128                });
129            }
130        };
131
132        match self.validity.try_into_mut() {
133            Ok(validity_mut) => Ok(BoolVectorMut {
134                bits,
135                validity: validity_mut,
136            }),
137            Err(validity) => Err(Self {
138                bits: bits.freeze(),
139                validity,
140            }),
141        }
142    }
143
144    fn into_mut(self) -> BoolVectorMut {
145        BoolVectorMut {
146            bits: self.bits.into_mut(),
147            validity: self.validity.into_mut(),
148        }
149    }
150}