vortex_array/arrays/bool/
mod.rs1use arrow_array::BooleanArray;
2use arrow_buffer::MutableBuffer;
3
4use crate::validity::Validity;
5
6mod array;
7pub mod compute;
8mod patch;
9mod serde;
10mod stats;
11
12pub use array::*;
13pub use arrow_buffer::{BooleanBuffer, BooleanBufferBuilder};
15
16impl BoolArray {
17 pub fn from_indices<I: IntoIterator<Item = usize>>(length: usize, indices: I) -> Self {
20 let mut buffer = MutableBuffer::new_null(length);
21 indices
22 .into_iter()
23 .for_each(|idx| arrow_buffer::bit_util::set_bit(&mut buffer, idx));
24 Self::new(
25 BooleanBufferBuilder::new_from_buffer(buffer, length).finish(),
26 Validity::NonNullable,
27 )
28 }
29}
30
31impl From<BooleanBuffer> for BoolArray {
32 fn from(value: BooleanBuffer) -> Self {
33 Self::new(value, Validity::NonNullable)
34 }
35}
36
37impl FromIterator<bool> for BoolArray {
38 fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
39 Self::new(BooleanBuffer::from_iter(iter), Validity::NonNullable)
40 }
41}
42
43impl FromIterator<Option<bool>> for BoolArray {
44 fn from_iter<I: IntoIterator<Item = Option<bool>>>(iter: I) -> Self {
45 let (buffer, nulls) = BooleanArray::from_iter(iter).into_parts();
46 Self::new(
47 buffer,
48 nulls.map(Validity::from).unwrap_or(Validity::AllValid),
49 )
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use arrow_buffer::{BooleanBuffer, BooleanBufferBuilder};
56 use vortex_buffer::buffer;
57
58 use crate::ToCanonical;
59 use crate::array::Array;
60 use crate::arrays::{BoolArray, PrimitiveArray};
61 use crate::compute::test_harness::test_mask;
62 use crate::compute::{scalar_at, slice};
63 use crate::patches::Patches;
64 use crate::validity::Validity;
65
66 #[test]
67 fn bool_array() {
68 let arr = BoolArray::from_iter([true, false, true]);
69 let scalar = bool::try_from(&scalar_at(&arr, 0).unwrap()).unwrap();
70 assert!(scalar);
71 }
72
73 #[test]
74 fn test_all_some_iter() {
75 let arr = BoolArray::from_iter([Some(true), Some(false)]);
76
77 assert!(matches!(arr.validity(), Validity::AllValid));
78
79 let scalar = bool::try_from(&scalar_at(&arr, 0).unwrap()).unwrap();
80 assert!(scalar);
81 let scalar = bool::try_from(&scalar_at(&arr, 1).unwrap()).unwrap();
82 assert!(!scalar);
83 }
84
85 #[test]
86 fn test_bool_from_iter() {
87 let arr = BoolArray::from_iter([Some(true), Some(true), None, Some(false), None]);
88
89 let scalar = bool::try_from(&scalar_at(&arr, 0).unwrap()).unwrap();
90 assert!(scalar);
91
92 let scalar = bool::try_from(&scalar_at(&arr, 1).unwrap()).unwrap();
93 assert!(scalar);
94
95 let scalar = scalar_at(&arr, 2).unwrap();
96 assert!(scalar.is_null());
97
98 let scalar = bool::try_from(&scalar_at(&arr, 3).unwrap()).unwrap();
99 assert!(!scalar);
100
101 let scalar = scalar_at(&arr, 4).unwrap();
102 assert!(scalar.is_null());
103 }
104
105 #[test]
106 fn patch_sliced_bools() {
107 let arr = {
108 let mut builder = BooleanBufferBuilder::new(12);
109 builder.append(false);
110 builder.append_n(11, true);
111 BoolArray::from(builder.finish())
112 };
113 let sliced = slice(&arr, 4, 12).unwrap();
114 let sliced_len = sliced.len();
115 let (values, offset) = sliced.to_bool().unwrap().into_boolean_builder();
116 assert_eq!(offset, 4);
117 assert_eq!(values.as_slice(), &[254, 15]);
118
119 let patches = Patches::new(
121 arr.len(),
122 0,
123 PrimitiveArray::new(buffer![4u32], Validity::AllValid).into_array(),
124 BoolArray::from(BooleanBuffer::new_unset(1)).into_array(),
125 );
126 let arr = arr.patch(&patches).unwrap();
127 let arr_len = arr.len();
128 let (values, offset) = arr.to_bool().unwrap().into_boolean_builder();
129 assert_eq!(offset, 0);
130 assert_eq!(values.len(), arr_len + offset);
131 assert_eq!(values.as_slice(), &[238, 15]);
132
133 let (values, offset) = sliced.to_bool().unwrap().into_boolean_builder();
135 assert_eq!(offset, 4);
136 assert_eq!(values.len(), sliced_len + offset);
137 assert_eq!(values.as_slice(), &[254, 15]); }
139
140 #[test]
141 fn slice_array_in_middle() {
142 let arr = BoolArray::from(BooleanBuffer::new_set(16));
143 let sliced = slice(&arr, 4, 12).unwrap();
144 let sliced_len = sliced.len();
145 let (values, offset) = sliced.to_bool().unwrap().into_boolean_builder();
146 assert_eq!(offset, 4);
147 assert_eq!(values.len(), sliced_len + offset);
148 assert_eq!(values.as_slice(), &[255, 15]);
149 }
150
151 #[test]
152 #[should_panic]
153 fn patch_bools_owned() {
154 let buffer = buffer![255u8; 2];
155 let buf = BooleanBuffer::new(buffer.into_arrow_buffer(), 0, 15);
156 let arr = BoolArray::new(buf, Validity::NonNullable);
157 let buf_ptr = arr.boolean_buffer().sliced().as_ptr();
158
159 let patches = Patches::new(
160 arr.len(),
161 0,
162 PrimitiveArray::new(buffer![0u32], Validity::AllValid).into_array(),
163 BoolArray::from(BooleanBuffer::new_unset(1)).into_array(),
164 );
165 let arr = arr.patch(&patches).unwrap();
166 assert_eq!(arr.boolean_buffer().sliced().as_ptr(), buf_ptr);
167
168 let (values, _byte_bit_offset) = arr.to_bool().unwrap().into_boolean_builder();
169 assert_eq!(values.as_slice(), &[254, 127]);
170 }
171
172 #[test]
173 fn test_mask_primitive_array() {
174 test_mask(&BoolArray::from_iter([true, false, true, true, false]));
175 }
176}