Coverage Report

Created: 2025-11-17 14:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/Users/andrewlamb/Software/arrow-rs/arrow-array/src/array/boolean_array.rs
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
use crate::array::print_long_array;
19
use crate::builder::BooleanBuilder;
20
use crate::iterator::BooleanIter;
21
use crate::{Array, ArrayAccessor, ArrayRef, Scalar};
22
use arrow_buffer::{BooleanBuffer, Buffer, MutableBuffer, NullBuffer, bit_util};
23
use arrow_data::{ArrayData, ArrayDataBuilder};
24
use arrow_schema::DataType;
25
use std::any::Any;
26
use std::sync::Arc;
27
28
/// An array of [boolean values](https://arrow.apache.org/docs/format/Columnar.html#fixed-size-primitive-layout)
29
///
30
/// # Example: From a Vec
31
///
32
/// ```
33
/// # use arrow_array::{Array, BooleanArray};
34
/// let arr: BooleanArray = vec![true, true, false].into();
35
/// ```
36
///
37
/// # Example: From an optional Vec
38
///
39
/// ```
40
/// # use arrow_array::{Array, BooleanArray};
41
/// let arr: BooleanArray = vec![Some(true), None, Some(false)].into();
42
/// ```
43
///
44
/// # Example: From an iterator
45
///
46
/// ```
47
/// # use arrow_array::{Array, BooleanArray};
48
/// let arr: BooleanArray = (0..5).map(|x| (x % 2 == 0).then(|| x % 3 == 0)).collect();
49
/// let values: Vec<_> = arr.iter().collect();
50
/// assert_eq!(&values, &[Some(true), None, Some(false), None, Some(false)])
51
/// ```
52
///
53
/// # Example: Using Builder
54
///
55
/// ```
56
/// # use arrow_array::Array;
57
/// # use arrow_array::builder::BooleanBuilder;
58
/// let mut builder = BooleanBuilder::new();
59
/// builder.append_value(true);
60
/// builder.append_null();
61
/// builder.append_value(false);
62
/// let array = builder.finish();
63
/// let values: Vec<_> = array.iter().collect();
64
/// assert_eq!(&values, &[Some(true), None, Some(false)])
65
/// ```
66
///
67
#[derive(Clone)]
68
pub struct BooleanArray {
69
    values: BooleanBuffer,
70
    nulls: Option<NullBuffer>,
71
}
72
73
impl std::fmt::Debug for BooleanArray {
74
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
75
0
        write!(f, "BooleanArray\n[\n")?;
76
0
        print_long_array(self, f, |array, index, f| {
77
0
            std::fmt::Debug::fmt(&array.value(index), f)
78
0
        })?;
79
0
        write!(f, "]")
80
0
    }
81
}
82
83
impl BooleanArray {
84
    /// Create a new [`BooleanArray`] from the provided values and nulls
85
    ///
86
    /// # Panics
87
    ///
88
    /// Panics if `values.len() != nulls.len()`
89
27
    pub fn new(values: BooleanBuffer, nulls: Option<NullBuffer>) -> Self {
90
27
        if let Some(
n11
) = nulls.as_ref() {
91
11
            assert_eq!(values.len(), n.len());
92
16
        }
93
27
        Self { values, nulls }
94
27
    }
95
96
    /// Create a new [`BooleanArray`] with length `len` consisting only of nulls
97
1
    pub fn new_null(len: usize) -> Self {
98
1
        Self {
99
1
            values: BooleanBuffer::new_unset(len),
100
1
            nulls: Some(NullBuffer::new_null(len)),
101
1
        }
102
1
    }
103
104
    /// Create a new [`Scalar`] from `value`
105
0
    pub fn new_scalar(value: bool) -> Scalar<Self> {
106
0
        let values = match value {
107
0
            true => BooleanBuffer::new_set(1),
108
0
            false => BooleanBuffer::new_unset(1),
109
        };
110
0
        Scalar::new(Self::new(values, None))
111
0
    }
112
113
    /// Create a new [`BooleanArray`] from a [`Buffer`] specified by `offset` and `len`, the `offset` and `len` in bits
114
    /// Logically convert each bit in [`Buffer`] to boolean and use it to build [`BooleanArray`].
115
    /// using this method will make the following points self-evident:
116
    /// * there is no `null` in the constructed [`BooleanArray`];
117
    /// * without considering `buffer.into()`, this method is efficient because there is no need to perform pack and unpack operations on boolean;
118
    pub fn new_from_packed(buffer: impl Into<Buffer>, offset: usize, len: usize) -> Self {
119
        BooleanBuffer::new(buffer.into(), offset, len).into()
120
    }
121
122
    /// Create a new [`BooleanArray`] from `&[u8]`
123
    /// This method uses `new_from_packed` and constructs a [`Buffer`] using `value`, and offset is set to 0 and len is set to `value.len() * 8`
124
    /// using this method will make the following points self-evident:
125
    /// * there is no `null` in the constructed [`BooleanArray`];
126
    /// * the length of the constructed [`BooleanArray`] is always a multiple of 8;
127
0
    pub fn new_from_u8(value: &[u8]) -> Self {
128
0
        BooleanBuffer::new(Buffer::from(value), 0, value.len() * 8).into()
129
0
    }
130
131
    /// Returns the length of this array.
132
2.73k
    pub fn len(&self) -> usize {
133
2.73k
        self.values.len()
134
2.73k
    }
135
136
    /// Returns whether this array is empty.
137
0
    pub fn is_empty(&self) -> bool {
138
0
        self.values.is_empty()
139
0
    }
140
141
    /// Returns a zero-copy slice of this array with the indicated offset and length.
142
877
    pub fn slice(&self, offset: usize, length: usize) -> Self {
143
        Self {
144
877
            values: self.values.slice(offset, length),
145
877
            nulls: self.nulls.as_ref().map(|n| 
n766
.
slice766
(
offset766
,
length766
)),
146
        }
147
877
    }
148
149
    /// Returns a new boolean array builder
150
0
    pub fn builder(capacity: usize) -> BooleanBuilder {
151
0
        BooleanBuilder::with_capacity(capacity)
152
0
    }
153
154
    /// Returns the underlying [`BooleanBuffer`] holding all the values of this array
155
3.11k
    pub fn values(&self) -> &BooleanBuffer {
156
3.11k
        &self.values
157
3.11k
    }
158
159
    /// Returns the number of non null, true values within this array
160
0
    pub fn true_count(&self) -> usize {
161
0
        match self.nulls() {
162
0
            Some(nulls) => {
163
0
                let null_chunks = nulls.inner().bit_chunks().iter_padded();
164
0
                let value_chunks = self.values().bit_chunks().iter_padded();
165
0
                null_chunks
166
0
                    .zip(value_chunks)
167
0
                    .map(|(a, b)| (a & b).count_ones() as usize)
168
0
                    .sum()
169
            }
170
0
            None => self.values().count_set_bits(),
171
        }
172
0
    }
173
174
    /// Returns the number of non null, false values within this array
175
0
    pub fn false_count(&self) -> usize {
176
0
        self.len() - self.null_count() - self.true_count()
177
0
    }
178
179
    /// Returns the boolean value at index `i`.
180
    ///
181
    /// Note: This method does not check for nulls and the value is arbitrary
182
    /// if [`is_null`](Self::is_null) returns true for the index.
183
    ///
184
    /// # Safety
185
    /// This doesn't check bounds, the caller must ensure that index < self.len()
186
18.4k
    pub unsafe fn value_unchecked(&self, i: usize) -> bool {
187
18.4k
        unsafe { self.values.value_unchecked(i) }
188
18.4k
    }
189
190
    /// Returns the boolean value at index `i`.
191
    ///
192
    /// Note: This method does not check for nulls and the value is arbitrary
193
    /// if [`is_null`](Self::is_null) returns true for the index.
194
    ///
195
    /// # Panics
196
    /// Panics if index `i` is out of bounds
197
0
    pub fn value(&self, i: usize) -> bool {
198
0
        assert!(
199
0
            i < self.len(),
200
0
            "Trying to access an element at index {} from a BooleanArray of length {}",
201
            i,
202
0
            self.len()
203
        );
204
        // Safety:
205
        // `i < self.len()
206
0
        unsafe { self.value_unchecked(i) }
207
0
    }
208
209
    /// Returns an iterator that returns the values of `array.value(i)` for an iterator with each element `i`
210
    pub fn take_iter<'a>(
211
        &'a self,
212
        indexes: impl Iterator<Item = Option<usize>> + 'a,
213
    ) -> impl Iterator<Item = Option<bool>> + 'a {
214
        indexes.map(|opt_index| opt_index.map(|index| self.value(index)))
215
    }
216
217
    /// Returns an iterator that returns the values of `array.value(i)` for an iterator with each element `i`
218
    /// # Safety
219
    ///
220
    /// caller must ensure that the offsets in the iterator are less than the array len()
221
    pub unsafe fn take_iter_unchecked<'a>(
222
        &'a self,
223
        indexes: impl Iterator<Item = Option<usize>> + 'a,
224
    ) -> impl Iterator<Item = Option<bool>> + 'a {
225
        indexes.map(|opt_index| opt_index.map(|index| unsafe { self.value_unchecked(index) }))
226
    }
227
228
    /// Create a [`BooleanArray`] by evaluating the operation for
229
    /// each element of the provided array
230
    ///
231
    /// ```
232
    /// # use arrow_array::{BooleanArray, Int32Array};
233
    ///
234
    /// let array = Int32Array::from(vec![1, 2, 3, 4, 5]);
235
    /// let r = BooleanArray::from_unary(&array, |x| x > 2);
236
    /// assert_eq!(&r, &BooleanArray::from(vec![false, false, true, true, true]));
237
    /// ```
238
5
    pub fn from_unary<T: ArrayAccessor, F>(left: T, mut op: F) -> Self
239
5
    where
240
5
        F: FnMut(T::Item) -> bool,
241
    {
242
5
        let nulls = left.logical_nulls();
243
5
        let values = BooleanBuffer::collect_bool(left.len(), |i| unsafe {
244
            // SAFETY: i in range 0..len
245
23
            op(left.value_unchecked(i))
246
23
        });
247
5
        Self::new(values, nulls)
248
5
    }
249
250
    /// Create a [`BooleanArray`] by evaluating the binary operation for
251
    /// each element of the provided arrays
252
    ///
253
    /// ```
254
    /// # use arrow_array::{BooleanArray, Int32Array};
255
    ///
256
    /// let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
257
    /// let b = Int32Array::from(vec![1, 2, 0, 2, 5]);
258
    /// let r = BooleanArray::from_binary(&a, &b, |a, b| a == b);
259
    /// assert_eq!(&r, &BooleanArray::from(vec![true, true, false, false, true]));
260
    /// ```
261
    ///
262
    /// # Panics
263
    ///
264
    /// This function panics if left and right are not the same length
265
    ///
266
    pub fn from_binary<T: ArrayAccessor, S: ArrayAccessor, F>(left: T, right: S, mut op: F) -> Self
267
    where
268
        F: FnMut(T::Item, S::Item) -> bool,
269
    {
270
        assert_eq!(left.len(), right.len());
271
272
        let nulls = NullBuffer::union(
273
            left.logical_nulls().as_ref(),
274
            right.logical_nulls().as_ref(),
275
        );
276
        let values = BooleanBuffer::collect_bool(left.len(), |i| unsafe {
277
            // SAFETY: i in range 0..len
278
            op(left.value_unchecked(i), right.value_unchecked(i))
279
        });
280
        Self::new(values, nulls)
281
    }
282
283
    /// Deconstruct this array into its constituent parts
284
4
    pub fn into_parts(self) -> (BooleanBuffer, Option<NullBuffer>) {
285
4
        (self.values, self.nulls)
286
4
    }
287
}
288
289
impl Array for BooleanArray {
290
116
    fn as_any(&self) -> &dyn Any {
291
116
        self
292
116
    }
293
294
22
    fn to_data(&self) -> ArrayData {
295
22
        self.clone().into()
296
22
    }
297
298
0
    fn into_data(self) -> ArrayData {
299
0
        self.into()
300
0
    }
301
302
26
    fn data_type(&self) -> &DataType {
303
26
        &DataType::Boolean
304
26
    }
305
306
1
    fn slice(&self, offset: usize, length: usize) -> ArrayRef {
307
1
        Arc::new(self.slice(offset, length))
308
1
    }
309
310
791
    fn len(&self) -> usize {
311
791
        self.values.len()
312
791
    }
313
314
0
    fn is_empty(&self) -> bool {
315
0
        self.values.is_empty()
316
0
    }
317
318
0
    fn shrink_to_fit(&mut self) {
319
0
        self.values.shrink_to_fit();
320
0
        if let Some(nulls) = &mut self.nulls {
321
0
            nulls.shrink_to_fit();
322
0
        }
323
0
    }
324
325
0
    fn offset(&self) -> usize {
326
0
        self.values.offset()
327
0
    }
328
329
3.54k
    fn nulls(&self) -> Option<&NullBuffer> {
330
3.54k
        self.nulls.as_ref()
331
3.54k
    }
332
333
0
    fn logical_null_count(&self) -> usize {
334
0
        self.null_count()
335
0
    }
336
337
0
    fn get_buffer_memory_size(&self) -> usize {
338
0
        let mut sum = self.values.inner().capacity();
339
0
        if let Some(x) = &self.nulls {
340
0
            sum += x.buffer().capacity()
341
0
        }
342
0
        sum
343
0
    }
344
345
0
    fn get_array_memory_size(&self) -> usize {
346
0
        std::mem::size_of::<Self>() + self.get_buffer_memory_size()
347
0
    }
348
}
349
350
impl ArrayAccessor for &BooleanArray {
351
    type Item = bool;
352
353
0
    fn value(&self, index: usize) -> Self::Item {
354
0
        BooleanArray::value(self, index)
355
0
    }
356
357
18.4k
    unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
358
18.4k
        unsafe { BooleanArray::value_unchecked(self, index) }
359
18.4k
    }
360
}
361
362
impl From<Vec<bool>> for BooleanArray {
363
130
    fn from(data: Vec<bool>) -> Self {
364
130
        let mut mut_buf = MutableBuffer::new_null(data.len());
365
        {
366
130
            let mut_slice = mut_buf.as_slice_mut();
367
973
            for (i, b) in 
data.iter()130
.
enumerate130
() {
368
973
                if *b {
369
545
                    bit_util::set_bit(mut_slice, i);
370
545
                
}428
371
            }
372
        }
373
130
        let array_data = ArrayData::builder(DataType::Boolean)
374
130
            .len(data.len())
375
130
            .add_buffer(mut_buf.into());
376
377
130
        let array_data = unsafe { array_data.build_unchecked() };
378
130
        BooleanArray::from(array_data)
379
130
    }
380
}
381
382
impl From<Vec<Option<bool>>> for BooleanArray {
383
24
    fn from(data: Vec<Option<bool>>) -> Self {
384
24
        data.iter().collect()
385
24
    }
386
}
387
388
impl From<ArrayData> for BooleanArray {
389
2.12k
    fn from(data: ArrayData) -> Self {
390
2.12k
        assert_eq!(
391
2.12k
            data.data_type(),
392
            &DataType::Boolean,
393
0
            "BooleanArray expected ArrayData with type {} got {}",
394
            DataType::Boolean,
395
0
            data.data_type()
396
        );
397
2.12k
        assert_eq!(
398
2.12k
            data.buffers().len(),
399
            1,
400
0
            "BooleanArray data should contain a single buffer only (values buffer)"
401
        );
402
2.12k
        let values = BooleanBuffer::new(data.buffers()[0].clone(), data.offset(), data.len());
403
404
2.12k
        Self {
405
2.12k
            values,
406
2.12k
            nulls: data.nulls().cloned(),
407
2.12k
        }
408
2.12k
    }
409
}
410
411
impl From<BooleanArray> for ArrayData {
412
22
    fn from(array: BooleanArray) -> Self {
413
22
        let builder = ArrayDataBuilder::new(DataType::Boolean)
414
22
            .len(array.values.len())
415
22
            .offset(array.values.offset())
416
22
            .nulls(array.nulls)
417
22
            .buffers(vec![array.values.into_inner()]);
418
419
22
        unsafe { builder.build_unchecked() }
420
22
    }
421
}
422
423
impl<'a> IntoIterator for &'a BooleanArray {
424
    type Item = Option<bool>;
425
    type IntoIter = BooleanIter<'a>;
426
427
0
    fn into_iter(self) -> Self::IntoIter {
428
0
        BooleanIter::<'a>::new(self)
429
0
    }
430
}
431
432
impl<'a> BooleanArray {
433
    /// constructs a new iterator
434
768
    pub fn iter(&'a self) -> BooleanIter<'a> {
435
768
        BooleanIter::<'a>::new(self)
436
768
    }
437
}
438
439
/// An optional boolean value
440
///
441
/// This struct is used as an adapter when creating `BooleanArray` from an iterator.
442
/// `FromIterator` for `BooleanArray` takes an iterator where the elements can be `into`
443
/// this struct. So once implementing `From` or `Into` trait for a type, an iterator of
444
/// the type can be collected to `BooleanArray`.
445
///
446
/// See also [NativeAdapter](crate::array::NativeAdapter).
447
#[derive(Debug)]
448
struct BooleanAdapter {
449
    /// Corresponding Rust native type if available
450
    pub native: Option<bool>,
451
}
452
453
impl From<bool> for BooleanAdapter {
454
14
    fn from(value: bool) -> Self {
455
14
        BooleanAdapter {
456
14
            native: Some(value),
457
14
        }
458
14
    }
459
}
460
461
impl From<&bool> for BooleanAdapter {
462
0
    fn from(value: &bool) -> Self {
463
0
        BooleanAdapter {
464
0
            native: Some(*value),
465
0
        }
466
0
    }
467
}
468
469
impl From<Option<bool>> for BooleanAdapter {
470
647k
    fn from(value: Option<bool>) -> Self {
471
647k
        BooleanAdapter { native: value }
472
647k
    }
473
}
474
475
impl From<&Option<bool>> for BooleanAdapter {
476
138
    fn from(value: &Option<bool>) -> Self {
477
138
        BooleanAdapter { native: *value }
478
138
    }
479
}
480
481
impl<Ptr: Into<BooleanAdapter>> FromIterator<Ptr> for BooleanArray {
482
939
    fn from_iter<I: IntoIterator<Item = Ptr>>(iter: I) -> Self {
483
939
        let iter = iter.into_iter();
484
939
        let capacity = match iter.size_hint() {
485
939
            (lower, Some(upper)) if lower == upper => lower,
486
0
            _ => 0,
487
        };
488
939
        let mut builder = BooleanBuilder::with_capacity(capacity);
489
324k
        
builder939
.
extend939
(
iter939
.
map939
(|item| item.into().native));
490
939
        builder.finish()
491
939
    }
492
}
493
494
impl BooleanArray {
495
    /// Creates a [`BooleanArray`] from an iterator of trusted length.
496
    ///
497
    /// # Safety
498
    ///
499
    /// The iterator must be [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html).
500
    /// I.e. that `size_hint().1` correctly reports its length. Note that this is a stronger
501
    /// guarantee that `ExactSizeIterator` provides which could still report a wrong length.
502
    ///
503
    /// # Panics
504
    ///
505
    /// Panics if the iterator does not report an upper bound on `size_hint()`.
506
    #[inline]
507
    #[allow(
508
        private_bounds,
509
        reason = "We will expose BooleanAdapter if there is a need"
510
    )]
511
939
    pub unsafe fn from_trusted_len_iter<I, P>(iter: I) -> Self
512
939
    where
513
939
        P: Into<BooleanAdapter>,
514
939
        I: ExactSizeIterator<Item = P>,
515
    {
516
939
        let data_len = iter.len();
517
518
939
        let num_bytes = bit_util::ceil(data_len, 8);
519
939
        let mut null_builder = MutableBuffer::from_len_zeroed(num_bytes);
520
939
        let mut val_builder = MutableBuffer::from_len_zeroed(num_bytes);
521
522
939
        let data = val_builder.as_slice_mut();
523
524
939
        let null_slice = null_builder.as_slice_mut();
525
324k
        
iter939
.
enumerate939
().
for_each939
(|(i, item)| {
526
324k
            if let Some(
a293k
) = item.into().native {
527
                unsafe {
528
                    // SAFETY: There will be enough space in the buffers due to the trusted len size
529
                    // hint
530
293k
                    bit_util::set_bit_raw(null_slice.as_mut_ptr(), i);
531
293k
                    if a {
532
38.2k
                        bit_util::set_bit_raw(data.as_mut_ptr(), i);
533
255k
                    }
534
                }
535
30.7k
            }
536
324k
        });
537
538
939
        let data = unsafe {
539
939
            ArrayData::new_unchecked(
540
939
                DataType::Boolean,
541
939
                data_len,
542
939
                None,
543
939
                Some(null_builder.into()),
544
                0,
545
939
                vec![val_builder.into()],
546
939
                vec![],
547
            )
548
        };
549
939
        BooleanArray::from(data)
550
939
    }
551
}
552
553
impl From<BooleanBuffer> for BooleanArray {
554
4
    fn from(values: BooleanBuffer) -> Self {
555
4
        Self {
556
4
            values,
557
4
            nulls: None,
558
4
        }
559
4
    }
560
}
561
562
#[cfg(test)]
563
mod tests {
564
    use super::*;
565
    use arrow_buffer::Buffer;
566
    use rand::{Rng, rng};
567
568
    #[test]
569
    fn test_boolean_fmt_debug() {
570
        let arr = BooleanArray::from(vec![true, false, false]);
571
        assert_eq!(
572
            "BooleanArray\n[\n  true,\n  false,\n  false,\n]",
573
            format!("{arr:?}")
574
        );
575
    }
576
577
    #[test]
578
    fn test_boolean_with_null_fmt_debug() {
579
        let mut builder = BooleanArray::builder(3);
580
        builder.append_value(true);
581
        builder.append_null();
582
        builder.append_value(false);
583
        let arr = builder.finish();
584
        assert_eq!(
585
            "BooleanArray\n[\n  true,\n  null,\n  false,\n]",
586
            format!("{arr:?}")
587
        );
588
    }
589
590
    #[test]
591
    fn test_boolean_array_from_vec() {
592
        let buf = Buffer::from([10_u8]);
593
        let arr = BooleanArray::from(vec![false, true, false, true]);
594
        assert_eq!(&buf, arr.values().inner());
595
        assert_eq!(4, arr.len());
596
        assert_eq!(0, arr.offset());
597
        assert_eq!(0, arr.null_count());
598
        for i in 0..4 {
599
            assert!(!arr.is_null(i));
600
            assert!(arr.is_valid(i));
601
            assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
602
        }
603
    }
604
605
    #[test]
606
    fn test_boolean_array_from_vec_option() {
607
        let buf = Buffer::from([10_u8]);
608
        let arr = BooleanArray::from(vec![Some(false), Some(true), None, Some(true)]);
609
        assert_eq!(&buf, arr.values().inner());
610
        assert_eq!(4, arr.len());
611
        assert_eq!(0, arr.offset());
612
        assert_eq!(1, arr.null_count());
613
        for i in 0..4 {
614
            if i == 2 {
615
                assert!(arr.is_null(i));
616
                assert!(!arr.is_valid(i));
617
            } else {
618
                assert!(!arr.is_null(i));
619
                assert!(arr.is_valid(i));
620
                assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
621
            }
622
        }
623
    }
624
625
    #[test]
626
    fn test_boolean_array_from_packed() {
627
        let v = [1_u8, 2_u8, 3_u8];
628
        let arr = BooleanArray::new_from_packed(v, 0, 24);
629
        assert_eq!(24, arr.len());
630
        assert_eq!(0, arr.offset());
631
        assert_eq!(0, arr.null_count());
632
        assert!(arr.nulls.is_none());
633
        for i in 0..24 {
634
            assert!(!arr.is_null(i));
635
            assert!(arr.is_valid(i));
636
            assert_eq!(
637
                i == 0 || i == 9 || i == 16 || i == 17,
638
                arr.value(i),
639
                "failed t {i}"
640
            )
641
        }
642
    }
643
644
    #[test]
645
    fn test_boolean_array_from_slice_u8() {
646
        let v: Vec<u8> = vec![1, 2, 3];
647
        let slice = &v[..];
648
        let arr = BooleanArray::new_from_u8(slice);
649
        assert_eq!(24, arr.len());
650
        assert_eq!(0, arr.offset());
651
        assert_eq!(0, arr.null_count());
652
        assert!(arr.nulls().is_none());
653
        for i in 0..24 {
654
            assert!(!arr.is_null(i));
655
            assert!(arr.is_valid(i));
656
            assert_eq!(
657
                i == 0 || i == 9 || i == 16 || i == 17,
658
                arr.value(i),
659
                "failed t {i}"
660
            )
661
        }
662
    }
663
664
    #[test]
665
    fn test_boolean_array_from_iter() {
666
        let v = vec![Some(false), Some(true), Some(false), Some(true)];
667
        let arr = v.into_iter().collect::<BooleanArray>();
668
        assert_eq!(4, arr.len());
669
        assert_eq!(0, arr.offset());
670
        assert_eq!(0, arr.null_count());
671
        assert!(arr.nulls().is_none());
672
        for i in 0..3 {
673
            assert!(!arr.is_null(i));
674
            assert!(arr.is_valid(i));
675
            assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
676
        }
677
    }
678
679
    #[test]
680
    fn test_boolean_array_from_non_nullable_iter() {
681
        let v = vec![true, false, true];
682
        let arr = v.into_iter().collect::<BooleanArray>();
683
        assert_eq!(3, arr.len());
684
        assert_eq!(0, arr.offset());
685
        assert_eq!(0, arr.null_count());
686
        assert!(arr.nulls().is_none());
687
688
        assert!(arr.value(0));
689
        assert!(!arr.value(1));
690
        assert!(arr.value(2));
691
    }
692
693
    #[test]
694
    fn test_boolean_array_from_nullable_iter() {
695
        let v = vec![Some(true), None, Some(false), None];
696
        let arr = v.into_iter().collect::<BooleanArray>();
697
        assert_eq!(4, arr.len());
698
        assert_eq!(0, arr.offset());
699
        assert_eq!(2, arr.null_count());
700
        assert!(arr.nulls().is_some());
701
702
        assert!(arr.is_valid(0));
703
        assert!(arr.is_null(1));
704
        assert!(arr.is_valid(2));
705
        assert!(arr.is_null(3));
706
707
        assert!(arr.value(0));
708
        assert!(!arr.value(2));
709
    }
710
711
    #[test]
712
    fn test_boolean_array_from_nullable_trusted_len_iter() {
713
        // Should exhibit the same behavior as `from_iter`, which is tested above.
714
        let v = vec![Some(true), None, Some(false), None];
715
        let expected = v.clone().into_iter().collect::<BooleanArray>();
716
        let actual = unsafe {
717
            // SAFETY: `v` has trusted length
718
            BooleanArray::from_trusted_len_iter(v.into_iter())
719
        };
720
        assert_eq!(expected, actual);
721
    }
722
723
    #[test]
724
    fn test_boolean_array_from_iter_with_larger_upper_bound() {
725
        // See https://github.com/apache/arrow-rs/issues/8505
726
        // This returns an upper size hint of 4
727
        let iterator = vec![Some(true), None, Some(false), None]
728
            .into_iter()
729
            .filter(Option::is_some);
730
        let arr = iterator.collect::<BooleanArray>();
731
        assert_eq!(2, arr.len());
732
    }
733
734
    #[test]
735
    fn test_boolean_array_builder() {
736
        // Test building a boolean array with ArrayData builder and offset
737
        // 000011011
738
        let buf = Buffer::from([27_u8]);
739
        let buf2 = buf.clone();
740
        let data = ArrayData::builder(DataType::Boolean)
741
            .len(5)
742
            .offset(2)
743
            .add_buffer(buf)
744
            .build()
745
            .unwrap();
746
        let arr = BooleanArray::from(data);
747
        assert_eq!(&buf2, arr.values().inner());
748
        assert_eq!(5, arr.len());
749
        assert_eq!(2, arr.offset());
750
        assert_eq!(0, arr.null_count());
751
        for i in 0..3 {
752
            assert_eq!(i != 0, arr.value(i), "failed at {i}");
753
        }
754
    }
755
756
    #[test]
757
    #[should_panic(
758
        expected = "Trying to access an element at index 4 from a BooleanArray of length 3"
759
    )]
760
    fn test_fixed_size_binary_array_get_value_index_out_of_bound() {
761
        let v = vec![Some(true), None, Some(false)];
762
        let array = v.into_iter().collect::<BooleanArray>();
763
764
        array.value(4);
765
    }
766
767
    #[test]
768
    #[should_panic(expected = "BooleanArray data should contain a single buffer only \
769
                               (values buffer)")]
770
    // Different error messages, so skip for now
771
    // https://github.com/apache/arrow-rs/issues/1545
772
    #[cfg(not(feature = "force_validate"))]
773
    fn test_boolean_array_invalid_buffer_len() {
774
        let data = unsafe {
775
            ArrayData::builder(DataType::Boolean)
776
                .len(5)
777
                .build_unchecked()
778
        };
779
        drop(BooleanArray::from(data));
780
    }
781
782
    #[test]
783
    #[should_panic(expected = "BooleanArray expected ArrayData with type Boolean got Int32")]
784
    fn test_from_array_data_validation() {
785
        let _ = BooleanArray::from(ArrayData::new_empty(&DataType::Int32));
786
    }
787
788
    #[test]
789
    #[cfg_attr(miri, ignore)] // Takes too long
790
    fn test_true_false_count() {
791
        let mut rng = rng();
792
793
        for _ in 0..10 {
794
            // No nulls
795
            let d: Vec<_> = (0..2000).map(|_| rng.random_bool(0.5)).collect();
796
            let b = BooleanArray::from(d.clone());
797
798
            let expected_true = d.iter().filter(|x| **x).count();
799
            assert_eq!(b.true_count(), expected_true);
800
            assert_eq!(b.false_count(), d.len() - expected_true);
801
802
            // With nulls
803
            let d: Vec<_> = (0..2000)
804
                .map(|_| rng.random_bool(0.5).then(|| rng.random_bool(0.5)))
805
                .collect();
806
            let b = BooleanArray::from(d.clone());
807
808
            let expected_true = d.iter().filter(|x| matches!(x, Some(true))).count();
809
            assert_eq!(b.true_count(), expected_true);
810
811
            let expected_false = d.iter().filter(|x| matches!(x, Some(false))).count();
812
            assert_eq!(b.false_count(), expected_false);
813
        }
814
    }
815
816
    #[test]
817
    fn test_into_parts() {
818
        let boolean_array = [Some(true), None, Some(false)]
819
            .into_iter()
820
            .collect::<BooleanArray>();
821
        let (values, nulls) = boolean_array.into_parts();
822
        assert_eq!(values.values(), &[0b0000_0001]);
823
        assert!(nulls.is_some());
824
        assert_eq!(nulls.unwrap().buffer().as_slice(), &[0b0000_0101]);
825
826
        let boolean_array =
827
            BooleanArray::from(vec![false, false, false, false, false, false, false, true]);
828
        let (values, nulls) = boolean_array.into_parts();
829
        assert_eq!(values.values(), &[0b1000_0000]);
830
        assert!(nulls.is_none());
831
    }
832
}