From 042033257bc70da909a47d65926c011029c84122 Mon Sep 17 00:00:00 2001 From: chloro <13125187405@163.com> Date: Thu, 25 Jul 2024 21:00:14 +0800 Subject: [PATCH] Support construct BooleanArray from &[u8] --- arrow-array/src/array/boolean_array.rs | 42 ++++++++++++++++++++++++++ arrow-buffer/src/buffer/boolean.rs | 30 ++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/arrow-array/src/array/boolean_array.rs b/arrow-array/src/array/boolean_array.rs index fe374d965714..532fb2c21904 100644 --- a/arrow-array/src/array/boolean_array.rs +++ b/arrow-array/src/array/boolean_array.rs @@ -50,6 +50,22 @@ use std::sync::Arc; /// assert_eq!(&values, &[Some(true), None, Some(false), None, Some(false)]) /// ``` /// +/// # Example: From &[u8] +/// +/// ``` +/// # use arrow_array::{Array, BooleanArray}; +/// let v: Vec = vec![1]; +/// let slice = &v[..]; +/// let arr = BooleanArray::from(slice); +/// assert_eq!(8, arr.len()); +/// assert!(!arr.is_null(0)); +/// assert!(arr.value(0)); +/// ``` +/// convert each bit in `&[u8]` to boolean and use it to build [`BooleanArray`]. +/// using this method will make the following two points self-evident: +/// * There is no `null` in the constructed [`BooleanArray`] +/// * The length of the constructed [`BooleanArray`] is always a multiple of 8; +/// /// # Example: Using Builder /// /// ``` @@ -349,6 +365,12 @@ impl From>> for BooleanArray { } } +impl From<&[u8]> for BooleanArray { + fn from(value: &[u8]) -> Self { + Self::from(BooleanBuffer::from(value)) + } +} + impl From for BooleanArray { fn from(data: ArrayData) -> Self { assert_eq!( @@ -509,6 +531,26 @@ mod tests { } } + #[test] + fn test_boolean_array_from_slice_u8() { + let v: Vec = vec![1, 2, 3]; + let slice = &v[..]; + let arr = BooleanArray::from(slice); + assert_eq!(24, arr.len()); + assert_eq!(0, arr.offset()); + assert_eq!(0, arr.null_count()); + assert!(arr.nulls().is_none()); + for i in 0..24 { + assert!(!arr.is_null(i)); + assert!(arr.is_valid(i)); + assert_eq!( + i == 0 || i == 9 || i == 16 || i == 17, + arr.value(i), + "failed t {i}" + ) + } + } + #[test] fn test_boolean_array_from_iter() { let v = vec![Some(false), Some(true), Some(false), Some(true)]; diff --git a/arrow-buffer/src/buffer/boolean.rs b/arrow-buffer/src/buffer/boolean.rs index 1589cc5b102b..7a14eb3fa33b 100644 --- a/arrow-buffer/src/buffer/boolean.rs +++ b/arrow-buffer/src/buffer/boolean.rs @@ -21,6 +21,7 @@ use crate::{ bit_util, buffer_bin_and, buffer_bin_or, buffer_bin_xor, buffer_unary_not, BooleanBufferBuilder, Buffer, MutableBuffer, }; + use std::ops::{BitAnd, BitOr, BitXor, Not}; /// A slice-able [`Buffer`] containing bit-packed booleans @@ -274,6 +275,12 @@ impl From<&[bool]> for BooleanBuffer { } } +impl From<&[u8]> for BooleanBuffer { + fn from(slice: &[u8]) -> Self { + BooleanBuffer::new(Buffer::from(slice), 0, slice.len() * 8) + } +} + impl From> for BooleanBuffer { fn from(value: Vec) -> Self { value.as_slice().into() @@ -414,4 +421,27 @@ mod tests { let expected = BooleanBuffer::new(Buffer::from(&[255, 254, 254, 255, 255]), offset, len); assert_eq!(!boolean_buf, expected); } + + #[test] + fn test_boolean_from_slice_bool() { + let v = [true, false, false]; + let buf = BooleanBuffer::from(&v[..]); + assert_eq!(buf.offset(), 0); + assert_eq!(buf.len(), 3); + assert_eq!(buf.values().len(), 1); + assert!(buf.value(0)); + } + + #[test] + fn test_boolean_from_slice_u8() { + let v = [1_u8, 2, 3]; + let buf = BooleanBuffer::from(&v[..]); + assert_eq!(buf.offset(), 0); + assert_eq!(buf.len(), 24); + assert_eq!(buf.values().len(), 3); + assert!(buf.value(0)); + assert!(buf.value(9)); + assert!(buf.value(16)); + assert!(buf.value(17)); + } }