Skip to content

Commit 9b08bf2

Browse files
committed
save
Signed-off-by: Andrew Duffy <andrew@a10y.dev>
1 parent 655082c commit 9b08bf2

File tree

3 files changed

+31
-14
lines changed

3 files changed

+31
-14
lines changed

encodings/bytebool/src/array.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ use vortex_array::vtable::VTable;
2929
use vortex_array::vtable::ValidityVTable;
3030
use vortex_array::vtable::child_to_validity;
3131
use vortex_array::vtable::validity_to_child;
32-
use vortex_buffer::BitBuffer;
3332
use vortex_buffer::ByteBuffer;
33+
use vortex_buffer::{BitBuffer, BitBufferMut};
3434
use vortex_error::VortexExpect as _;
3535
use vortex_error::VortexResult;
3636
use vortex_error::vortex_bail;
@@ -151,7 +151,8 @@ impl VTable for ByteBool {
151151
}
152152

153153
fn execute(array: Array<Self>, _ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
154-
let boolean_buffer = BitBuffer::from(array.as_slice());
154+
// convert truthy values to set/unset bits
155+
let boolean_buffer = BitBufferMut::from(array.truthy_bytes()).freeze();
155156
let validity = array.validity()?;
156157
Ok(ExecutionResult::done(
157158
BoolArray::new(boolean_buffer, validity).into_array(),
@@ -225,7 +226,7 @@ impl ByteBool {
225226
/// # Safety
226227
///
227228
/// Every byte of `buffer` must be `0x00` or `0x01`. Any other byte value is
228-
/// Undefined Behavior because [`ByteBoolData::as_slice`] reinterprets the buffer
229+
/// Undefined Behavior because [`ByteBoolData::truthy_bytes`] reinterprets the buffer
229230
/// as `&[bool]`, and a `bool` with any bit pattern other than 0 or 1 is UB.
230231
/// If `validity` is [`Validity::Array`], its length must equal `buffer.len()`.
231232
pub unsafe fn new_unchecked(buffer: BufferHandle, validity: Validity) -> ByteBoolArray {
@@ -295,7 +296,7 @@ impl ByteBoolData {
295296

296297
/// Validate that every byte of `buffer` is `0x00` or `0x01`.
297298
///
298-
/// [`ByteBoolData::as_slice`] transmutes the buffer's bytes to `&[bool]`; any byte
299+
/// [`ByteBoolData::truthy_bytes`] transmutes the buffer's bytes to `&[bool]`; any byte
299300
/// other than `0x00` or `0x01` would produce a `bool` with an invalid bit pattern,
300301
/// which is Undefined Behavior per the Rust reference.
301302
///
@@ -345,7 +346,7 @@ impl ByteBoolData {
345346
/// # Safety
346347
///
347348
/// Every byte of `buffer` must be `0x00` or `0x01`. Any other byte value is
348-
/// Undefined Behavior because [`ByteBoolData::as_slice`] reinterprets the buffer
349+
/// Undefined Behavior because [`ByteBoolData::truthy_bytes`] reinterprets the buffer
349350
/// as `&[bool]`, and a `bool` with any bit pattern other than 0 or 1 is UB.
350351
/// If `validity` is [`Validity::Array`], its length must equal `buffer.len()`.
351352
pub unsafe fn new_unchecked(buffer: BufferHandle, validity: Validity) -> Self {
@@ -394,9 +395,11 @@ impl ByteBoolData {
394395
&self.buffer
395396
}
396397

397-
pub fn as_slice(&self) -> &[bool] {
398-
// Safety: The internal buffer contains byte-sized bools
399-
unsafe { std::mem::transmute(self.buffer().as_host().as_slice()) }
398+
/// Get access to the underlying 8-bit truthy values.
399+
///
400+
/// The zero byte indicates `false`, and any non-zero byte is a `true`.
401+
pub fn truthy_bytes(&self) -> &[u8] {
402+
self.buffer().as_host().as_slice()
400403
}
401404
}
402405

@@ -514,7 +517,7 @@ mod tests {
514517
// SAFETY: all bytes are 0 or 1.
515518
let arr = unsafe { ByteBool::new_unchecked(handle, Validity::NonNullable) };
516519
assert_eq!(arr.len(), 4);
517-
assert_eq!(arr.as_slice(), &[false, true, true, false]);
520+
assert_eq!(arr.truthy_bytes(), &[false, true, true, false]);
518521
}
519522

520523
#[test]

encodings/bytebool/src/compute.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ use vortex_array::ExecutionCtx;
88
use vortex_array::IntoArray;
99
use vortex_array::arrays::PrimitiveArray;
1010
use vortex_array::arrays::dict::TakeExecute;
11+
use vortex_array::buffer::BufferHandle;
1112
use vortex_array::dtype::DType;
1213
use vortex_array::match_each_integer_ptype;
1314
use vortex_array::scalar_fn::fns::cast::CastReduce;
1415
use vortex_array::scalar_fn::fns::mask::MaskReduce;
1516
use vortex_array::validity::Validity;
17+
use vortex_buffer::ByteBuffer;
1618
use vortex_error::VortexResult;
1719

1820
use super::ByteBool;
@@ -58,23 +60,28 @@ impl TakeExecute for ByteBool {
5860
ctx: &mut ExecutionCtx,
5961
) -> VortexResult<Option<ArrayRef>> {
6062
let indices = indices.clone().execute::<PrimitiveArray>(ctx)?;
61-
let bools = array.as_slice();
63+
let values = array.truthy_bytes();
6264

6365
// This handles combining validity from both source array and nullable indices
6466
let validity = array.validity()?.take(&indices.clone().into_array())?;
6567

66-
let taken_bools = match_each_integer_ptype!(indices.ptype(), |I| {
68+
let taken = match_each_integer_ptype!(indices.ptype(), |I| {
6769
indices
6870
.as_slice::<I>()
6971
.iter()
7072
.map(|&idx| {
7173
let idx: usize = idx.as_();
72-
bools[idx]
74+
values[idx]
7375
})
74-
.collect::<Vec<bool>>()
76+
.collect::<ByteBuffer>()
7577
});
7678

77-
Ok(Some(ByteBool::from_vec(taken_bools, validity).into_array()))
79+
// SAFETY:
80+
unsafe {
81+
Ok(Some(
82+
ByteBool::new_unchecked(BufferHandle::new_host(taken), validity).into_array(),
83+
))
84+
}
7885
}
7986
}
8087

vortex-buffer/src/bit/buf_mut.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,13 @@ impl From<&[bool]> for BitBufferMut {
573573
}
574574
}
575575

576+
// allow building a buffer from a set of truthy byte values.
577+
impl From<&[u8]> for BitBufferMut {
578+
fn from(value: &[u8]) -> Self {
579+
BitBufferMut::collect_bool(value.len(), |i| value[i] > 0)
580+
}
581+
}
582+
576583
impl From<Vec<bool>> for BitBufferMut {
577584
fn from(value: Vec<bool>) -> Self {
578585
value.as_slice().into()

0 commit comments

Comments
 (0)