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