• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vortex-data / vortex / 16979224669

14 Aug 2025 11:42PM UTC coverage: 23.728%. First build
16979224669

Pull #2456

github

web-flow
Merge 30049dfa7 into aaf3e36ad
Pull Request #2456: feat: basic BoolBuffer / BoolBufferMut

68 of 1065 new or added lines in 82 files covered. (6.38%)

8616 of 36312 relevant lines covered (23.73%)

146.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.41
/encodings/bytebool/src/array.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::fmt::Debug;
5

6
use vortex_array::arrays::BoolArray;
7
use vortex_array::stats::{ArrayStats, StatsSetRef};
8
use vortex_array::validity::Validity;
9
use vortex_array::vtable::{
10
    ArrayVTable, CanonicalVTable, NotSupported, OperationsVTable, VTable, ValidityHelper,
11
    ValidityVTableFromValidityHelper,
12
};
13
use vortex_array::{ArrayRef, Canonical, EncodingId, EncodingRef, IntoArray, vtable};
14
use vortex_buffer::{BitBuffer, ByteBuffer};
15
use vortex_dtype::DType;
16
use vortex_error::{VortexResult, vortex_panic};
17
use vortex_scalar::Scalar;
18

19
vtable!(ByteBool);
20

21
impl VTable for ByteBoolVTable {
22
    type Array = ByteBoolArray;
23
    type Encoding = ByteBoolEncoding;
24

25
    type ArrayVTable = Self;
26
    type CanonicalVTable = Self;
27
    type OperationsVTable = Self;
28
    type ValidityVTable = ValidityVTableFromValidityHelper;
29
    type VisitorVTable = Self;
30
    type ComputeVTable = NotSupported;
31
    type EncodeVTable = NotSupported;
32
    type SerdeVTable = Self;
33

34
    fn id(_encoding: &Self::Encoding) -> EncodingId {
2✔
35
        EncodingId::new_ref("vortex.bytebool")
2✔
36
    }
2✔
37

38
    fn encoding(_array: &Self::Array) -> EncodingRef {
×
39
        EncodingRef::new_ref(ByteBoolEncoding.as_ref())
×
40
    }
×
41
}
42

43
#[derive(Clone, Debug)]
44
pub struct ByteBoolArray {
45
    dtype: DType,
46
    buffer: ByteBuffer,
47
    validity: Validity,
48
    stats_set: ArrayStats,
49
}
50

51
#[derive(Clone, Debug)]
52
pub struct ByteBoolEncoding;
53

54
impl ByteBoolArray {
55
    pub fn new(buffer: ByteBuffer, validity: Validity) -> Self {
×
56
        let length = buffer.len();
×
57
        if let Some(vlen) = validity.maybe_len()
×
58
            && length != vlen
×
59
        {
60
            vortex_panic!(
×
61
                "Buffer length ({}) does not match validity length ({})",
×
62
                length,
63
                vlen
64
            );
65
        }
×
66
        Self {
×
67
            dtype: DType::Bool(validity.nullability()),
×
68
            buffer,
×
69
            validity,
×
70
            stats_set: Default::default(),
×
71
        }
×
72
    }
×
73

74
    // TODO(ngates): deprecate construction from vec
75
    pub fn from_vec<V: Into<Validity>>(data: Vec<bool>, validity: V) -> Self {
×
76
        let validity = validity.into();
×
77
        // SAFETY: we are transmuting a Vec<bool> into a Vec<u8>
78
        let data: Vec<u8> = unsafe { std::mem::transmute(data) };
×
79
        Self::new(ByteBuffer::from(data), validity)
×
80
    }
×
81

82
    pub fn buffer(&self) -> &ByteBuffer {
×
83
        &self.buffer
×
84
    }
×
85

86
    pub fn as_slice(&self) -> &[bool] {
×
87
        // Safety: The internal buffer contains byte-sized bools
88
        unsafe { std::mem::transmute(self.buffer().as_slice()) }
×
89
    }
×
90
}
91

92
impl ValidityHelper for ByteBoolArray {
93
    fn validity(&self) -> &Validity {
×
94
        &self.validity
×
95
    }
×
96
}
97

98
impl ArrayVTable<ByteBoolVTable> for ByteBoolVTable {
99
    fn len(array: &ByteBoolArray) -> usize {
×
100
        array.buffer.len()
×
101
    }
×
102

103
    fn dtype(array: &ByteBoolArray) -> &DType {
×
104
        &array.dtype
×
105
    }
×
106

107
    fn stats(array: &ByteBoolArray) -> StatsSetRef<'_> {
×
108
        array.stats_set.to_ref(array.as_ref())
×
109
    }
×
110
}
111

112
impl CanonicalVTable<ByteBoolVTable> for ByteBoolVTable {
113
    fn canonicalize(array: &ByteBoolArray) -> VortexResult<Canonical> {
×
NEW
114
        let boolean_buffer = BitBuffer::from(array.as_slice());
×
115
        let validity = array.validity().clone();
×
116
        Ok(Canonical::Bool(BoolArray::new(boolean_buffer, validity)))
×
117
    }
×
118
}
119

120
impl OperationsVTable<ByteBoolVTable> for ByteBoolVTable {
121
    fn slice(array: &ByteBoolArray, start: usize, stop: usize) -> VortexResult<ArrayRef> {
×
122
        Ok(ByteBoolArray::new(
×
123
            array.buffer().slice(start..stop),
×
124
            array.validity().slice(start, stop)?,
×
125
        )
126
        .into_array())
×
127
    }
×
128

129
    fn scalar_at(array: &ByteBoolArray, index: usize) -> VortexResult<Scalar> {
×
130
        Ok(Scalar::bool(
×
131
            array.buffer()[index] == 1,
×
132
            array.dtype().nullability(),
×
133
        ))
×
134
    }
×
135
}
136

137
impl From<Vec<bool>> for ByteBoolArray {
138
    fn from(value: Vec<bool>) -> Self {
×
139
        Self::from_vec(value, Validity::AllValid)
×
140
    }
×
141
}
142

143
impl From<Vec<Option<bool>>> for ByteBoolArray {
144
    fn from(value: Vec<Option<bool>>) -> Self {
×
145
        let validity = Validity::from_iter(value.iter().map(|v| v.is_some()));
×
146

147
        // This doesn't reallocate, and the compiler even vectorizes it
148
        let data = value.into_iter().map(Option::unwrap_or_default).collect();
×
149

150
        Self::from_vec(data, validity)
×
151
    }
×
152
}
153

154
#[cfg(test)]
155
mod tests {
156
    use super::*;
157

158
    // #[cfg_attr(miri, ignore)]
159
    // #[test]
160
    // fn test_bytebool_metadata() {
161
    //     check_metadata(
162
    //         "bytebool.metadata",
163
    //         SerdeMetadata(ByteBoolMetadata {
164
    //             validity: ValidityMetadata::AllValid,
165
    //         }),
166
    //     );
167
    // }
168

169
    #[test]
170
    fn test_validity_construction() {
171
        let v = vec![true, false];
172
        let v_len = v.len();
173

174
        let arr = ByteBoolArray::from(v);
175
        assert_eq!(v_len, arr.len());
176

177
        for idx in 0..arr.len() {
178
            assert!(arr.is_valid(idx).unwrap());
179
        }
180

181
        let v = vec![Some(true), None, Some(false)];
182
        let arr = ByteBoolArray::from(v);
183
        assert!(arr.is_valid(0).unwrap());
184
        assert!(!arr.is_valid(1).unwrap());
185
        assert!(arr.is_valid(2).unwrap());
186
        assert_eq!(arr.len(), 3);
187

188
        let v: Vec<Option<bool>> = vec![None, None];
189
        let v_len = v.len();
190

191
        let arr = ByteBoolArray::from(v);
192
        assert_eq!(v_len, arr.len());
193

194
        for idx in 0..arr.len() {
195
            assert!(!arr.is_valid(idx).unwrap());
196
        }
197
        assert_eq!(arr.len(), 2);
198
    }
199
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc