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

vortex-data / vortex / 16810706267

07 Aug 2025 04:52PM UTC coverage: 84.907% (+0.05%) from 84.856%
16810706267

Pull #4159

github

web-flow
Merge 80c87ff6a into cc5d64403
Pull Request #4159: chore: Bump msrv to 1.89

107 of 157 new or added lines in 34 files covered. (68.15%)

2 existing lines in 2 files now uncovered.

50642 of 59644 relevant lines covered (84.91%)

567883.04 hits per line

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

97.75
/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 arrow_buffer::BooleanBuffer;
7
use vortex_array::arrays::BoolArray;
8
use vortex_array::stats::{ArrayStats, StatsSetRef};
9
use vortex_array::validity::Validity;
10
use vortex_array::vtable::{
11
    ArrayVTable, CanonicalVTable, NotSupported, OperationsVTable, VTable, ValidityHelper,
12
    ValidityVTableFromValidityHelper,
13
};
14
use vortex_array::{ArrayRef, Canonical, EncodingId, EncodingRef, IntoArray, vtable};
15
use vortex_buffer::ByteBuffer;
16
use vortex_dtype::DType;
17
use vortex_error::{VortexResult, vortex_panic};
18
use vortex_scalar::Scalar;
19

20
vtable!(ByteBool);
21

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

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

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

39
    fn encoding(_array: &Self::Array) -> EncodingRef {
1,879✔
40
        EncodingRef::new_ref(ByteBoolEncoding.as_ref())
1,879✔
41
    }
1,879✔
42
}
43

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

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

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

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

83
    pub fn buffer(&self) -> &ByteBuffer {
871✔
84
        &self.buffer
871✔
85
    }
871✔
86

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

93
impl ValidityHelper for ByteBoolArray {
94
    fn validity(&self) -> &Validity {
1,464✔
95
        &self.validity
1,464✔
96
    }
1,464✔
97
}
98

99
impl ArrayVTable<ByteBoolVTable> for ByteBoolVTable {
100
    fn len(array: &ByteBoolArray) -> usize {
3,391✔
101
        array.buffer.len()
3,391✔
102
    }
3,391✔
103

104
    fn dtype(array: &ByteBoolArray) -> &DType {
3,397✔
105
        &array.dtype
3,397✔
106
    }
3,397✔
107

108
    fn stats(array: &ByteBoolArray) -> StatsSetRef<'_> {
1,045✔
109
        array.stats_set.to_ref(array.as_ref())
1,045✔
110
    }
1,045✔
111
}
112

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

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

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

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

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

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

151
        Self::from_vec(data, validity)
12✔
152
    }
12✔
153
}
154

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

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

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

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

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

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

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

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

195
        for idx in 0..arr.len() {
2✔
196
            assert!(!arr.is_valid(idx).unwrap());
2✔
197
        }
198
        assert_eq!(arr.len(), 2);
1✔
199
    }
1✔
200
}
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