Skip to main content

arrow_array/array/
boolean_array.rs

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
18use crate::array::print_long_array;
19use crate::builder::BooleanBuilder;
20use crate::iterator::BooleanIter;
21use crate::{Array, ArrayAccessor, ArrayRef, Scalar};
22use arrow_buffer::{BooleanBuffer, Buffer, MutableBuffer, NullBuffer, bit_util};
23use arrow_data::{ArrayData, ArrayDataBuilder};
24use arrow_schema::DataType;
25use std::any::Any;
26use 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)]
68pub struct BooleanArray {
69    values: BooleanBuffer,
70    nulls: Option<NullBuffer>,
71}
72
73impl std::fmt::Debug for BooleanArray {
74    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
75        write!(f, "BooleanArray\n[\n")?;
76        print_long_array(self, f, |array, index, f| {
77            std::fmt::Debug::fmt(&array.value(index), f)
78        })?;
79        write!(f, "]")
80    }
81}
82
83impl BooleanArray {
84    /// Create a new [`BooleanArray`] from the provided values and nulls
85    ///
86    /// # Panics
87    ///
88    /// Panics if `values.len() != nulls.len()`
89    pub fn new(values: BooleanBuffer, nulls: Option<NullBuffer>) -> Self {
90        if let Some(n) = nulls.as_ref() {
91            assert_eq!(values.len(), n.len());
92        }
93        Self { values, nulls }
94    }
95
96    /// Create a new [`BooleanArray`] with length `len` consisting only of nulls
97    pub fn new_null(len: usize) -> Self {
98        Self {
99            values: BooleanBuffer::new_unset(len),
100            nulls: Some(NullBuffer::new_null(len)),
101        }
102    }
103
104    /// Create a new [`Scalar`] from `value`
105    pub fn new_scalar(value: bool) -> Scalar<Self> {
106        let values = match value {
107            true => BooleanBuffer::new_set(1),
108            false => BooleanBuffer::new_unset(1),
109        };
110        Scalar::new(Self::new(values, None))
111    }
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    pub fn new_from_u8(value: &[u8]) -> Self {
128        BooleanBuffer::new(Buffer::from(value), 0, value.len() * 8).into()
129    }
130
131    /// Returns the length of this array.
132    pub fn len(&self) -> usize {
133        self.values.len()
134    }
135
136    /// Returns whether this array is empty.
137    pub fn is_empty(&self) -> bool {
138        self.values.is_empty()
139    }
140
141    /// Returns a zero-copy slice of this array with the indicated offset and length.
142    pub fn slice(&self, offset: usize, length: usize) -> Self {
143        Self {
144            values: self.values.slice(offset, length),
145            nulls: self.nulls.as_ref().map(|n| n.slice(offset, length)),
146        }
147    }
148
149    /// Returns a new boolean array builder
150    pub fn builder(capacity: usize) -> BooleanBuilder {
151        BooleanBuilder::with_capacity(capacity)
152    }
153
154    /// Returns the underlying [`BooleanBuffer`] holding all the values of this array
155    pub fn values(&self) -> &BooleanBuffer {
156        &self.values
157    }
158
159    /// Returns the number of non null, true values within this array
160    pub fn true_count(&self) -> usize {
161        match self.nulls() {
162            Some(nulls) => {
163                let null_chunks = nulls.inner().bit_chunks().iter_padded();
164                let value_chunks = self.values().bit_chunks().iter_padded();
165                null_chunks
166                    .zip(value_chunks)
167                    .map(|(a, b)| (a & b).count_ones() as usize)
168                    .sum()
169            }
170            None => self.values().count_set_bits(),
171        }
172    }
173
174    /// Returns the number of non null, false values within this array
175    pub fn false_count(&self) -> usize {
176        self.len() - self.null_count() - self.true_count()
177    }
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    pub unsafe fn value_unchecked(&self, i: usize) -> bool {
187        unsafe { self.values.value_unchecked(i) }
188    }
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    pub fn value(&self, i: usize) -> bool {
198        assert!(
199            i < self.len(),
200            "Trying to access an element at index {} from a BooleanArray of length {}",
201            i,
202            self.len()
203        );
204        // Safety:
205        // `i < self.len()
206        unsafe { self.value_unchecked(i) }
207    }
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    pub fn from_unary<T: ArrayAccessor, F>(left: T, mut op: F) -> Self
239    where
240        F: FnMut(T::Item) -> bool,
241    {
242        let nulls = left.logical_nulls();
243        let values = BooleanBuffer::collect_bool(left.len(), |i| unsafe {
244            // SAFETY: i in range 0..len
245            op(left.value_unchecked(i))
246        });
247        Self::new(values, nulls)
248    }
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    pub fn into_parts(self) -> (BooleanBuffer, Option<NullBuffer>) {
285        (self.values, self.nulls)
286    }
287}
288
289/// SAFETY: Correctly implements the contract of Arrow Arrays
290unsafe impl Array for BooleanArray {
291    fn as_any(&self) -> &dyn Any {
292        self
293    }
294
295    fn to_data(&self) -> ArrayData {
296        self.clone().into()
297    }
298
299    fn into_data(self) -> ArrayData {
300        self.into()
301    }
302
303    fn data_type(&self) -> &DataType {
304        &DataType::Boolean
305    }
306
307    fn slice(&self, offset: usize, length: usize) -> ArrayRef {
308        Arc::new(self.slice(offset, length))
309    }
310
311    fn len(&self) -> usize {
312        self.values.len()
313    }
314
315    fn is_empty(&self) -> bool {
316        self.values.is_empty()
317    }
318
319    fn shrink_to_fit(&mut self) {
320        self.values.shrink_to_fit();
321        if let Some(nulls) = &mut self.nulls {
322            nulls.shrink_to_fit();
323        }
324    }
325
326    fn offset(&self) -> usize {
327        self.values.offset()
328    }
329
330    fn nulls(&self) -> Option<&NullBuffer> {
331        self.nulls.as_ref()
332    }
333
334    fn logical_null_count(&self) -> usize {
335        self.null_count()
336    }
337
338    fn get_buffer_memory_size(&self) -> usize {
339        let mut sum = self.values.inner().capacity();
340        if let Some(x) = &self.nulls {
341            sum += x.buffer().capacity()
342        }
343        sum
344    }
345
346    fn get_array_memory_size(&self) -> usize {
347        std::mem::size_of::<Self>() + self.get_buffer_memory_size()
348    }
349}
350
351impl ArrayAccessor for &BooleanArray {
352    type Item = bool;
353
354    fn value(&self, index: usize) -> Self::Item {
355        BooleanArray::value(self, index)
356    }
357
358    unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
359        unsafe { BooleanArray::value_unchecked(self, index) }
360    }
361}
362
363impl From<Vec<bool>> for BooleanArray {
364    fn from(data: Vec<bool>) -> Self {
365        let mut mut_buf = MutableBuffer::new_null(data.len());
366        {
367            let mut_slice = mut_buf.as_slice_mut();
368            for (i, b) in data.iter().enumerate() {
369                if *b {
370                    bit_util::set_bit(mut_slice, i);
371                }
372            }
373        }
374        let array_data = ArrayData::builder(DataType::Boolean)
375            .len(data.len())
376            .add_buffer(mut_buf.into());
377
378        let array_data = unsafe { array_data.build_unchecked() };
379        BooleanArray::from(array_data)
380    }
381}
382
383impl From<Vec<Option<bool>>> for BooleanArray {
384    fn from(data: Vec<Option<bool>>) -> Self {
385        data.iter().collect()
386    }
387}
388
389impl From<ArrayData> for BooleanArray {
390    fn from(data: ArrayData) -> Self {
391        let (data_type, len, nulls, offset, mut buffers, _child_data) = data.into_parts();
392        assert_eq!(
393            data_type,
394            DataType::Boolean,
395            "BooleanArray expected ArrayData with type Boolean got {data_type:?}",
396        );
397        assert_eq!(
398            buffers.len(),
399            1,
400            "BooleanArray data should contain a single buffer only (values buffer)"
401        );
402        let buffer = buffers.pop().expect("checked above");
403        let values = BooleanBuffer::new(buffer, offset, len);
404
405        Self { values, nulls }
406    }
407}
408
409impl From<BooleanArray> for ArrayData {
410    fn from(array: BooleanArray) -> Self {
411        let builder = ArrayDataBuilder::new(DataType::Boolean)
412            .len(array.values.len())
413            .offset(array.values.offset())
414            .nulls(array.nulls)
415            .buffers(vec![array.values.into_inner()]);
416
417        unsafe { builder.build_unchecked() }
418    }
419}
420
421impl<'a> IntoIterator for &'a BooleanArray {
422    type Item = Option<bool>;
423    type IntoIter = BooleanIter<'a>;
424
425    fn into_iter(self) -> Self::IntoIter {
426        BooleanIter::<'a>::new(self)
427    }
428}
429
430impl<'a> BooleanArray {
431    /// constructs a new iterator
432    pub fn iter(&'a self) -> BooleanIter<'a> {
433        BooleanIter::<'a>::new(self)
434    }
435}
436
437/// An optional boolean value
438///
439/// This struct is used as an adapter when creating `BooleanArray` from an iterator.
440/// `FromIterator` for `BooleanArray` takes an iterator where the elements can be `into`
441/// this struct. So once implementing `From` or `Into` trait for a type, an iterator of
442/// the type can be collected to `BooleanArray`.
443///
444/// See also [NativeAdapter](crate::array::NativeAdapter).
445#[derive(Debug)]
446struct BooleanAdapter {
447    /// Corresponding Rust native type if available
448    pub native: Option<bool>,
449}
450
451impl From<bool> for BooleanAdapter {
452    fn from(value: bool) -> Self {
453        BooleanAdapter {
454            native: Some(value),
455        }
456    }
457}
458
459impl From<&bool> for BooleanAdapter {
460    fn from(value: &bool) -> Self {
461        BooleanAdapter {
462            native: Some(*value),
463        }
464    }
465}
466
467impl From<Option<bool>> for BooleanAdapter {
468    fn from(value: Option<bool>) -> Self {
469        BooleanAdapter { native: value }
470    }
471}
472
473impl From<&Option<bool>> for BooleanAdapter {
474    fn from(value: &Option<bool>) -> Self {
475        BooleanAdapter { native: *value }
476    }
477}
478
479impl<Ptr: Into<BooleanAdapter>> FromIterator<Ptr> for BooleanArray {
480    fn from_iter<I: IntoIterator<Item = Ptr>>(iter: I) -> Self {
481        let iter = iter.into_iter();
482        let capacity = match iter.size_hint() {
483            (lower, Some(upper)) if lower == upper => lower,
484            _ => 0,
485        };
486        let mut builder = BooleanBuilder::with_capacity(capacity);
487        builder.extend(iter.map(|item| item.into().native));
488        builder.finish()
489    }
490}
491
492impl BooleanArray {
493    /// Creates a [`BooleanArray`] from an iterator of trusted length.
494    ///
495    /// # Safety
496    ///
497    /// The iterator must be [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html).
498    /// I.e. that `size_hint().1` correctly reports its length. Note that this is a stronger
499    /// guarantee that `ExactSizeIterator` provides which could still report a wrong length.
500    ///
501    /// # Panics
502    ///
503    /// Panics if the iterator does not report an upper bound on `size_hint()`.
504    #[inline]
505    #[allow(
506        private_bounds,
507        reason = "We will expose BooleanAdapter if there is a need"
508    )]
509    pub unsafe fn from_trusted_len_iter<I, P>(iter: I) -> Self
510    where
511        P: Into<BooleanAdapter>,
512        I: ExactSizeIterator<Item = P>,
513    {
514        let data_len = iter.len();
515
516        let num_bytes = bit_util::ceil(data_len, 8);
517        let mut null_builder = MutableBuffer::from_len_zeroed(num_bytes);
518        let mut val_builder = MutableBuffer::from_len_zeroed(num_bytes);
519
520        let data = val_builder.as_slice_mut();
521
522        let null_slice = null_builder.as_slice_mut();
523        iter.enumerate().for_each(|(i, item)| {
524            if let Some(a) = item.into().native {
525                unsafe {
526                    // SAFETY: There will be enough space in the buffers due to the trusted len size
527                    // hint
528                    bit_util::set_bit_raw(null_slice.as_mut_ptr(), i);
529                    if a {
530                        bit_util::set_bit_raw(data.as_mut_ptr(), i);
531                    }
532                }
533            }
534        });
535
536        let values = BooleanBuffer::new(val_builder.into(), 0, data_len);
537        let nulls = Some(NullBuffer::new(BooleanBuffer::new(
538            null_builder.into(),
539            0,
540            data_len,
541        )))
542        .filter(|n| n.null_count() > 0);
543        BooleanArray::new(values, nulls)
544    }
545}
546
547impl From<BooleanBuffer> for BooleanArray {
548    fn from(values: BooleanBuffer) -> Self {
549        Self {
550            values,
551            nulls: None,
552        }
553    }
554}
555
556#[cfg(test)]
557mod tests {
558    use super::*;
559    use arrow_buffer::Buffer;
560    use rand::{Rng, rng};
561
562    #[test]
563    fn test_boolean_fmt_debug() {
564        let arr = BooleanArray::from(vec![true, false, false]);
565        assert_eq!(
566            "BooleanArray\n[\n  true,\n  false,\n  false,\n]",
567            format!("{arr:?}")
568        );
569    }
570
571    #[test]
572    fn test_boolean_with_null_fmt_debug() {
573        let mut builder = BooleanArray::builder(3);
574        builder.append_value(true);
575        builder.append_null();
576        builder.append_value(false);
577        let arr = builder.finish();
578        assert_eq!(
579            "BooleanArray\n[\n  true,\n  null,\n  false,\n]",
580            format!("{arr:?}")
581        );
582    }
583
584    #[test]
585    fn test_boolean_array_from_vec() {
586        let buf = Buffer::from([10_u8]);
587        let arr = BooleanArray::from(vec![false, true, false, true]);
588        assert_eq!(&buf, arr.values().inner());
589        assert_eq!(4, arr.len());
590        assert_eq!(0, arr.offset());
591        assert_eq!(0, arr.null_count());
592        for i in 0..4 {
593            assert!(!arr.is_null(i));
594            assert!(arr.is_valid(i));
595            assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
596        }
597    }
598
599    #[test]
600    fn test_boolean_array_from_vec_option() {
601        let buf = Buffer::from([10_u8]);
602        let arr = BooleanArray::from(vec![Some(false), Some(true), None, Some(true)]);
603        assert_eq!(&buf, arr.values().inner());
604        assert_eq!(4, arr.len());
605        assert_eq!(0, arr.offset());
606        assert_eq!(1, arr.null_count());
607        for i in 0..4 {
608            if i == 2 {
609                assert!(arr.is_null(i));
610                assert!(!arr.is_valid(i));
611            } else {
612                assert!(!arr.is_null(i));
613                assert!(arr.is_valid(i));
614                assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
615            }
616        }
617    }
618
619    #[test]
620    fn test_boolean_array_from_packed() {
621        let v = [1_u8, 2_u8, 3_u8];
622        let arr = BooleanArray::new_from_packed(v, 0, 24);
623        assert_eq!(24, arr.len());
624        assert_eq!(0, arr.offset());
625        assert_eq!(0, arr.null_count());
626        assert!(arr.nulls.is_none());
627        for i in 0..24 {
628            assert!(!arr.is_null(i));
629            assert!(arr.is_valid(i));
630            assert_eq!(
631                i == 0 || i == 9 || i == 16 || i == 17,
632                arr.value(i),
633                "failed t {i}"
634            )
635        }
636    }
637
638    #[test]
639    fn test_boolean_array_from_slice_u8() {
640        let v: Vec<u8> = vec![1, 2, 3];
641        let slice = &v[..];
642        let arr = BooleanArray::new_from_u8(slice);
643        assert_eq!(24, arr.len());
644        assert_eq!(0, arr.offset());
645        assert_eq!(0, arr.null_count());
646        assert!(arr.nulls().is_none());
647        for i in 0..24 {
648            assert!(!arr.is_null(i));
649            assert!(arr.is_valid(i));
650            assert_eq!(
651                i == 0 || i == 9 || i == 16 || i == 17,
652                arr.value(i),
653                "failed t {i}"
654            )
655        }
656    }
657
658    #[test]
659    fn test_boolean_array_from_iter() {
660        let v = vec![Some(false), Some(true), Some(false), Some(true)];
661        let arr = v.into_iter().collect::<BooleanArray>();
662        assert_eq!(4, arr.len());
663        assert_eq!(0, arr.offset());
664        assert_eq!(0, arr.null_count());
665        assert!(arr.nulls().is_none());
666        for i in 0..3 {
667            assert!(!arr.is_null(i));
668            assert!(arr.is_valid(i));
669            assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
670        }
671    }
672
673    #[test]
674    fn test_boolean_array_from_non_nullable_iter() {
675        let v = vec![true, false, true];
676        let arr = v.into_iter().collect::<BooleanArray>();
677        assert_eq!(3, arr.len());
678        assert_eq!(0, arr.offset());
679        assert_eq!(0, arr.null_count());
680        assert!(arr.nulls().is_none());
681
682        assert!(arr.value(0));
683        assert!(!arr.value(1));
684        assert!(arr.value(2));
685    }
686
687    #[test]
688    fn test_boolean_array_from_nullable_iter() {
689        let v = vec![Some(true), None, Some(false), None];
690        let arr = v.into_iter().collect::<BooleanArray>();
691        assert_eq!(4, arr.len());
692        assert_eq!(0, arr.offset());
693        assert_eq!(2, arr.null_count());
694        assert!(arr.nulls().is_some());
695
696        assert!(arr.is_valid(0));
697        assert!(arr.is_null(1));
698        assert!(arr.is_valid(2));
699        assert!(arr.is_null(3));
700
701        assert!(arr.value(0));
702        assert!(!arr.value(2));
703    }
704
705    #[test]
706    fn test_boolean_array_from_nullable_trusted_len_iter() {
707        // Should exhibit the same behavior as `from_iter`, which is tested above.
708        let v = vec![Some(true), None, Some(false), None];
709        let expected = v.clone().into_iter().collect::<BooleanArray>();
710        let actual = unsafe {
711            // SAFETY: `v` has trusted length
712            BooleanArray::from_trusted_len_iter(v.into_iter())
713        };
714        assert_eq!(expected, actual);
715    }
716
717    #[test]
718    fn test_boolean_array_from_iter_with_larger_upper_bound() {
719        // See https://github.com/apache/arrow-rs/issues/8505
720        // This returns an upper size hint of 4
721        let iterator = vec![Some(true), None, Some(false), None]
722            .into_iter()
723            .filter(Option::is_some);
724        let arr = iterator.collect::<BooleanArray>();
725        assert_eq!(2, arr.len());
726    }
727
728    #[test]
729    fn test_boolean_array_builder() {
730        // Test building a boolean array with ArrayData builder and offset
731        // 000011011
732        let buf = Buffer::from([27_u8]);
733        let buf2 = buf.clone();
734        let data = ArrayData::builder(DataType::Boolean)
735            .len(5)
736            .offset(2)
737            .add_buffer(buf)
738            .build()
739            .unwrap();
740        let arr = BooleanArray::from(data);
741        assert_eq!(&buf2, arr.values().inner());
742        assert_eq!(5, arr.len());
743        assert_eq!(2, arr.offset());
744        assert_eq!(0, arr.null_count());
745        for i in 0..3 {
746            assert_eq!(i != 0, arr.value(i), "failed at {i}");
747        }
748    }
749
750    #[test]
751    #[should_panic(
752        expected = "Trying to access an element at index 4 from a BooleanArray of length 3"
753    )]
754    fn test_fixed_size_binary_array_get_value_index_out_of_bound() {
755        let v = vec![Some(true), None, Some(false)];
756        let array = v.into_iter().collect::<BooleanArray>();
757
758        array.value(4);
759    }
760
761    #[test]
762    #[should_panic(expected = "BooleanArray data should contain a single buffer only \
763                               (values buffer)")]
764    // Different error messages, so skip for now
765    // https://github.com/apache/arrow-rs/issues/1545
766    #[cfg(not(feature = "force_validate"))]
767    fn test_boolean_array_invalid_buffer_len() {
768        let data = unsafe {
769            ArrayData::builder(DataType::Boolean)
770                .len(5)
771                .build_unchecked()
772        };
773        drop(BooleanArray::from(data));
774    }
775
776    #[test]
777    #[should_panic(expected = "BooleanArray expected ArrayData with type Boolean got Int32")]
778    fn test_from_array_data_validation() {
779        let _ = BooleanArray::from(ArrayData::new_empty(&DataType::Int32));
780    }
781
782    #[test]
783    #[cfg_attr(miri, ignore)] // Takes too long
784    fn test_true_false_count() {
785        let mut rng = rng();
786
787        for _ in 0..10 {
788            // No nulls
789            let d: Vec<_> = (0..2000).map(|_| rng.random_bool(0.5)).collect();
790            let b = BooleanArray::from(d.clone());
791
792            let expected_true = d.iter().filter(|x| **x).count();
793            assert_eq!(b.true_count(), expected_true);
794            assert_eq!(b.false_count(), d.len() - expected_true);
795
796            // With nulls
797            let d: Vec<_> = (0..2000)
798                .map(|_| rng.random_bool(0.5).then(|| rng.random_bool(0.5)))
799                .collect();
800            let b = BooleanArray::from(d.clone());
801
802            let expected_true = d.iter().filter(|x| matches!(x, Some(true))).count();
803            assert_eq!(b.true_count(), expected_true);
804
805            let expected_false = d.iter().filter(|x| matches!(x, Some(false))).count();
806            assert_eq!(b.false_count(), expected_false);
807        }
808    }
809
810    #[test]
811    fn test_into_parts() {
812        let boolean_array = [Some(true), None, Some(false)]
813            .into_iter()
814            .collect::<BooleanArray>();
815        let (values, nulls) = boolean_array.into_parts();
816        assert_eq!(values.values(), &[0b0000_0001]);
817        assert!(nulls.is_some());
818        assert_eq!(nulls.unwrap().buffer().as_slice(), &[0b0000_0101]);
819
820        let boolean_array =
821            BooleanArray::from(vec![false, false, false, false, false, false, false, true]);
822        let (values, nulls) = boolean_array.into_parts();
823        assert_eq!(values.values(), &[0b1000_0000]);
824        assert!(nulls.is_none());
825    }
826
827    #[test]
828    fn test_new_null_array() {
829        let arr = BooleanArray::new_null(5);
830
831        assert_eq!(arr.len(), 5);
832        assert_eq!(arr.null_count(), 5);
833        assert_eq!(arr.true_count(), 0);
834        assert_eq!(arr.false_count(), 0);
835
836        for i in 0..5 {
837            assert!(arr.is_null(i));
838            assert!(!arr.is_valid(i));
839        }
840    }
841
842    #[test]
843    fn test_slice_with_nulls() {
844        let arr = BooleanArray::from(vec![Some(true), None, Some(false)]);
845        let sliced = arr.slice(1, 2);
846
847        assert_eq!(sliced.len(), 2);
848        assert_eq!(sliced.null_count(), 1);
849
850        assert!(sliced.is_null(0));
851        assert!(sliced.is_valid(1));
852        assert!(!sliced.value(1));
853    }
854}