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::bit_chunk_iterator::UnalignedBitChunk;
23use arrow_buffer::{BooleanBuffer, Buffer, MutableBuffer, NullBuffer, bit_util};
24use arrow_data::{ArrayData, ArrayDataBuilder};
25use arrow_schema::DataType;
26use std::any::Any;
27use std::sync::Arc;
28
29/// An array of [boolean values](https://arrow.apache.org/docs/format/Columnar.html#fixed-size-primitive-layout)
30///
31/// # Example: From a Vec
32///
33/// ```
34/// # use arrow_array::{Array, BooleanArray};
35/// let arr: BooleanArray = vec![true, true, false].into();
36/// ```
37///
38/// # Example: From an optional Vec
39///
40/// ```
41/// # use arrow_array::{Array, BooleanArray};
42/// let arr: BooleanArray = vec![Some(true), None, Some(false)].into();
43/// ```
44///
45/// # Example: From an iterator
46///
47/// ```
48/// # use arrow_array::{Array, BooleanArray};
49/// let arr: BooleanArray = (0..5).map(|x| (x % 2 == 0).then(|| x % 3 == 0)).collect();
50/// let values: Vec<_> = arr.iter().collect();
51/// assert_eq!(&values, &[Some(true), None, Some(false), None, Some(false)])
52/// ```
53///
54/// # Example: Using Builder
55///
56/// ```
57/// # use arrow_array::Array;
58/// # use arrow_array::builder::BooleanBuilder;
59/// let mut builder = BooleanBuilder::new();
60/// builder.append_value(true);
61/// builder.append_null();
62/// builder.append_value(false);
63/// let array = builder.finish();
64/// let values: Vec<_> = array.iter().collect();
65/// assert_eq!(&values, &[Some(true), None, Some(false)])
66/// ```
67///
68#[derive(Clone)]
69pub struct BooleanArray {
70    values: BooleanBuffer,
71    nulls: Option<NullBuffer>,
72}
73
74impl std::fmt::Debug for BooleanArray {
75    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
76        write!(f, "BooleanArray\n[\n")?;
77        print_long_array(self, f, |array, index, f| {
78            std::fmt::Debug::fmt(&array.value(index), f)
79        })?;
80        write!(f, "]")
81    }
82}
83
84impl BooleanArray {
85    /// Create a new [`BooleanArray`] from the provided values and nulls
86    ///
87    /// # Panics
88    ///
89    /// Panics if `values.len() != nulls.len()`
90    pub fn new(values: BooleanBuffer, nulls: Option<NullBuffer>) -> Self {
91        if let Some(n) = nulls.as_ref() {
92            assert_eq!(values.len(), n.len());
93        }
94        Self { values, nulls }
95    }
96
97    /// Create a new [`BooleanArray`] with length `len` consisting only of nulls
98    pub fn new_null(len: usize) -> Self {
99        Self {
100            values: BooleanBuffer::new_unset(len),
101            nulls: Some(NullBuffer::new_null(len)),
102        }
103    }
104
105    /// Create a new [`Scalar`] from `value`
106    pub fn new_scalar(value: bool) -> Scalar<Self> {
107        let values = match value {
108            true => BooleanBuffer::new_set(1),
109            false => BooleanBuffer::new_unset(1),
110        };
111        Scalar::new(Self::new(values, None))
112    }
113
114    /// Create a new [`BooleanArray`] from a [`Buffer`] specified by `offset` and `len`, the `offset` and `len` in bits
115    /// Logically convert each bit in [`Buffer`] to boolean and use it to build [`BooleanArray`].
116    /// using this method will make the following points self-evident:
117    /// * there is no `null` in the constructed [`BooleanArray`];
118    /// * without considering `buffer.into()`, this method is efficient because there is no need to perform pack and unpack operations on boolean;
119    pub fn new_from_packed(buffer: impl Into<Buffer>, offset: usize, len: usize) -> Self {
120        BooleanBuffer::new(buffer.into(), offset, len).into()
121    }
122
123    /// Create a new [`BooleanArray`] from `&[u8]`
124    /// 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`
125    /// using this method will make the following points self-evident:
126    /// * there is no `null` in the constructed [`BooleanArray`];
127    /// * the length of the constructed [`BooleanArray`] is always a multiple of 8;
128    pub fn new_from_u8(value: &[u8]) -> Self {
129        BooleanBuffer::new(Buffer::from(value), 0, value.len() * 8).into()
130    }
131
132    /// Returns the length of this array.
133    pub fn len(&self) -> usize {
134        self.values.len()
135    }
136
137    /// Returns whether this array is empty.
138    pub fn is_empty(&self) -> bool {
139        self.values.is_empty()
140    }
141
142    /// Returns a zero-copy slice of this array with the indicated offset and length.
143    pub fn slice(&self, offset: usize, length: usize) -> Self {
144        Self {
145            values: self.values.slice(offset, length),
146            nulls: self.nulls.as_ref().map(|n| n.slice(offset, length)),
147        }
148    }
149
150    /// Returns a new boolean array builder
151    pub fn builder(capacity: usize) -> BooleanBuilder {
152        BooleanBuilder::with_capacity(capacity)
153    }
154
155    /// Returns the underlying [`BooleanBuffer`] holding all the values of this array
156    pub fn values(&self) -> &BooleanBuffer {
157        &self.values
158    }
159
160    /// Block size for chunked fold operations in [`Self::has_true`] and [`Self::has_false`].
161    /// Using `chunks_exact` with this size lets the compiler fully unroll the inner
162    /// fold (no inner branch/loop), enabling short-circuit exits every N chunks.
163    const CHUNK_FOLD_BLOCK_SIZE: usize = 16;
164
165    /// Returns an [`UnalignedBitChunk`] over this array's values.
166    fn unaligned_bit_chunks(&self) -> UnalignedBitChunk<'_> {
167        UnalignedBitChunk::new(self.values().values(), self.values().offset(), self.len())
168    }
169
170    /// Returns the number of non null, true values within this array.
171    /// If you only need to check if there is at least one true value, consider using `has_true()` which can short-circuit and be more efficient.
172    pub fn true_count(&self) -> usize {
173        match self.nulls() {
174            Some(nulls) => {
175                let null_chunks = nulls.inner().bit_chunks().iter_padded();
176                let value_chunks = self.values().bit_chunks().iter_padded();
177                null_chunks
178                    .zip(value_chunks)
179                    .map(|(a, b)| (a & b).count_ones() as usize)
180                    .sum()
181            }
182            None => self.values().count_set_bits(),
183        }
184    }
185
186    /// Returns the number of non null, false values within this array.
187    /// If you only need to check if there is at least one false value, consider using `has_false()` which can short-circuit and be more efficient.
188    pub fn false_count(&self) -> usize {
189        self.len() - self.null_count() - self.true_count()
190    }
191
192    /// Returns whether there is at least one non-null `true` value in this array.
193    ///
194    /// This is more efficient than `true_count() > 0` because it can short-circuit
195    /// as soon as a `true` value is found, without counting all set bits.
196    ///
197    /// Null values are not counted as `true`. Returns `false` for empty arrays.
198    pub fn has_true(&self) -> bool {
199        match self.nulls() {
200            Some(nulls) => {
201                let null_chunks = nulls.inner().bit_chunks().iter_padded();
202                let value_chunks = self.values().bit_chunks().iter_padded();
203                null_chunks.zip(value_chunks).any(|(n, v)| (n & v) != 0)
204            }
205            None => {
206                let bit_chunks = self.unaligned_bit_chunks();
207                let chunks = bit_chunks.chunks();
208                let mut exact = chunks.chunks_exact(Self::CHUNK_FOLD_BLOCK_SIZE);
209                let found = bit_chunks.prefix().unwrap_or(0) != 0
210                    || exact.any(|block| block.iter().fold(0u64, |acc, &c| acc | c) != 0);
211                found
212                    || exact.remainder().iter().any(|&c| c != 0)
213                    || bit_chunks.suffix().unwrap_or(0) != 0
214            }
215        }
216    }
217
218    /// Returns whether there is at least one non-null `false` value in this array.
219    ///
220    /// This is more efficient than `false_count() > 0` because it can short-circuit
221    /// as soon as a `false` value is found, without counting all set bits.
222    ///
223    /// Null values are not counted as `false`. Returns `false` for empty arrays.
224    pub fn has_false(&self) -> bool {
225        match self.nulls() {
226            Some(nulls) => {
227                let null_chunks = nulls.inner().bit_chunks().iter_padded();
228                let value_chunks = self.values().bit_chunks().iter_padded();
229                null_chunks.zip(value_chunks).any(|(n, v)| (n & !v) != 0)
230            }
231            None => {
232                let bit_chunks = self.unaligned_bit_chunks();
233                // UnalignedBitChunk zeros padding bits; fill them with 1s so
234                // they don't appear as false values.
235                let lead_mask = !((1u64 << bit_chunks.lead_padding()) - 1);
236                let trail_mask = if bit_chunks.trailing_padding() == 0 {
237                    u64::MAX
238                } else {
239                    (1u64 << (64 - bit_chunks.trailing_padding())) - 1
240                };
241                let (prefix_fill, suffix_fill) = match (bit_chunks.prefix(), bit_chunks.suffix()) {
242                    (Some(_), Some(_)) => (!lead_mask, !trail_mask),
243                    (Some(_), None) => (!lead_mask | !trail_mask, 0),
244                    (None, Some(_)) => (0, !trail_mask),
245                    (None, None) => (0, 0),
246                };
247                let chunks = bit_chunks.chunks();
248                let mut exact = chunks.chunks_exact(Self::CHUNK_FOLD_BLOCK_SIZE);
249                let found = bit_chunks
250                    .prefix()
251                    .is_some_and(|v| (v | prefix_fill) != u64::MAX)
252                    || exact
253                        .any(|block| block.iter().fold(u64::MAX, |acc, &c| acc & c) != u64::MAX);
254                found
255                    || exact.remainder().iter().any(|&c| c != u64::MAX)
256                    || bit_chunks
257                        .suffix()
258                        .is_some_and(|v| (v | suffix_fill) != u64::MAX)
259            }
260        }
261    }
262
263    /// Returns the boolean value at index `i`.
264    ///
265    /// Note: This method does not check for nulls and the value is arbitrary
266    /// if [`is_null`](Self::is_null) returns true for the index.
267    ///
268    /// # Safety
269    /// This doesn't check bounds, the caller must ensure that index < self.len()
270    pub unsafe fn value_unchecked(&self, i: usize) -> bool {
271        unsafe { self.values.value_unchecked(i) }
272    }
273
274    /// Returns the boolean value at index `i`.
275    ///
276    /// Note: This method does not check for nulls and the value is arbitrary
277    /// if [`is_null`](Self::is_null) returns true for the index.
278    ///
279    /// # Panics
280    /// Panics if index `i` is out of bounds
281    pub fn value(&self, i: usize) -> bool {
282        assert!(
283            i < self.len(),
284            "Trying to access an element at index {} from a BooleanArray of length {}",
285            i,
286            self.len()
287        );
288        // Safety:
289        // `i < self.len()
290        unsafe { self.value_unchecked(i) }
291    }
292
293    /// Returns an iterator that returns the values of `array.value(i)` for an iterator with each element `i`
294    pub fn take_iter<'a>(
295        &'a self,
296        indexes: impl Iterator<Item = Option<usize>> + 'a,
297    ) -> impl Iterator<Item = Option<bool>> + 'a {
298        indexes.map(|opt_index| opt_index.map(|index| self.value(index)))
299    }
300
301    /// Returns an iterator that returns the values of `array.value(i)` for an iterator with each element `i`
302    /// # Safety
303    ///
304    /// caller must ensure that the offsets in the iterator are less than the array len()
305    pub unsafe fn take_iter_unchecked<'a>(
306        &'a self,
307        indexes: impl Iterator<Item = Option<usize>> + 'a,
308    ) -> impl Iterator<Item = Option<bool>> + 'a {
309        indexes.map(|opt_index| opt_index.map(|index| unsafe { self.value_unchecked(index) }))
310    }
311
312    /// Create a [`BooleanArray`] by evaluating the operation for
313    /// each element of the provided array
314    ///
315    /// ```
316    /// # use arrow_array::{BooleanArray, Int32Array};
317    ///
318    /// let array = Int32Array::from(vec![1, 2, 3, 4, 5]);
319    /// let r = BooleanArray::from_unary(&array, |x| x > 2);
320    /// assert_eq!(&r, &BooleanArray::from(vec![false, false, true, true, true]));
321    /// ```
322    pub fn from_unary<T: ArrayAccessor, F>(left: T, mut op: F) -> Self
323    where
324        F: FnMut(T::Item) -> bool,
325    {
326        let nulls = left.logical_nulls();
327        let values = BooleanBuffer::collect_bool(left.len(), |i| unsafe {
328            // SAFETY: i in range 0..len
329            op(left.value_unchecked(i))
330        });
331        Self::new(values, nulls)
332    }
333
334    /// Create a [`BooleanArray`] by evaluating the binary operation for
335    /// each element of the provided arrays
336    ///
337    /// ```
338    /// # use arrow_array::{BooleanArray, Int32Array};
339    ///
340    /// let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
341    /// let b = Int32Array::from(vec![1, 2, 0, 2, 5]);
342    /// let r = BooleanArray::from_binary(&a, &b, |a, b| a == b);
343    /// assert_eq!(&r, &BooleanArray::from(vec![true, true, false, false, true]));
344    /// ```
345    ///
346    /// # Panics
347    ///
348    /// This function panics if left and right are not the same length
349    ///
350    pub fn from_binary<T: ArrayAccessor, S: ArrayAccessor, F>(left: T, right: S, mut op: F) -> Self
351    where
352        F: FnMut(T::Item, S::Item) -> bool,
353    {
354        assert_eq!(left.len(), right.len());
355
356        let nulls = NullBuffer::union(
357            left.logical_nulls().as_ref(),
358            right.logical_nulls().as_ref(),
359        );
360        let values = BooleanBuffer::collect_bool(left.len(), |i| unsafe {
361            // SAFETY: i in range 0..len
362            op(left.value_unchecked(i), right.value_unchecked(i))
363        });
364        Self::new(values, nulls)
365    }
366
367    /// Apply a bitwise operation to this array's values using u64 operations,
368    /// returning a new [`BooleanArray`].
369    ///
370    /// The null buffer is preserved unchanged.
371    ///
372    /// See [`BooleanBuffer::from_bitwise_unary_op`] for details on the operation.
373    ///
374    /// # Example
375    ///
376    /// ```
377    /// # use arrow_array::BooleanArray;
378    /// let array = BooleanArray::from(vec![true, false, true]);
379    /// let result = array.bitwise_unary(|x| !x);
380    /// assert_eq!(result, BooleanArray::from(vec![false, true, false]));
381    /// ```
382    pub fn bitwise_unary<F>(&self, op: F) -> BooleanArray
383    where
384        F: FnMut(u64) -> u64,
385    {
386        let values = BooleanBuffer::from_bitwise_unary_op(
387            self.values.values(),
388            self.values.offset(),
389            self.values.len(),
390            op,
391        );
392        BooleanArray::new(values, self.nulls.clone())
393    }
394
395    /// Try to apply a bitwise operation to this array's values in place using
396    /// u64 operations.
397    ///
398    /// If the underlying buffer is uniquely owned, the operation is applied
399    /// in place and `Ok` is returned. If the buffer is shared, `Err(self)` is
400    /// returned so the caller can fall back to [`bitwise_unary`](Self::bitwise_unary).
401    ///
402    /// The null buffer is preserved unchanged.
403    ///
404    /// # Example
405    ///
406    /// ```
407    /// # use arrow_array::BooleanArray;
408    /// let array = BooleanArray::from(vec![true, false, true]);
409    /// let result = array.bitwise_unary_mut(|x| !x).unwrap();
410    /// assert_eq!(result, BooleanArray::from(vec![false, true, false]));
411    /// ```
412    pub fn bitwise_unary_mut<F>(self, op: F) -> Result<BooleanArray, BooleanArray>
413    where
414        F: FnMut(u64) -> u64,
415    {
416        self.try_bitwise_unary_in_place(op)
417            .map_err(|(array, _op)| array)
418    }
419
420    /// Apply a bitwise operation to this array's values in place if the buffer
421    /// is uniquely owned, or clone and apply if shared.
422    ///
423    /// This is a convenience wrapper around [`bitwise_unary_mut`](Self::bitwise_unary_mut)
424    /// that falls back to [`bitwise_unary`](Self::bitwise_unary) when the buffer is shared.
425    ///
426    /// The null buffer is preserved unchanged.
427    ///
428    /// # Example
429    ///
430    /// ```
431    /// # use arrow_array::BooleanArray;
432    /// let array = BooleanArray::from(vec![true, false, true]);
433    /// let result = array.bitwise_unary_mut_or_clone(|x| !x);
434    /// assert_eq!(result, BooleanArray::from(vec![false, true, false]));
435    /// ```
436    pub fn bitwise_unary_mut_or_clone<F>(self, op: F) -> BooleanArray
437    where
438        F: FnMut(u64) -> u64,
439    {
440        match self.try_bitwise_unary_in_place(op) {
441            Ok(array) => array,
442            Err((array, op)) => array.bitwise_unary(op),
443        }
444    }
445
446    /// Try to apply a unary op in place. Returns `op` back on failure so
447    /// callers can fall back to an allocating path without requiring `F: Clone`.
448    fn try_bitwise_unary_in_place<F>(self, op: F) -> Result<BooleanArray, (BooleanArray, F)>
449    where
450        F: FnMut(u64) -> u64,
451    {
452        let (values, nulls) = self.into_parts();
453        let offset = values.offset();
454        let len = values.len();
455        let buffer = values.into_inner();
456        match buffer.into_mutable() {
457            Ok(mut buf) => {
458                bit_util::apply_bitwise_unary_op(buf.as_slice_mut(), offset, len, op);
459                let values = BooleanBuffer::new(buf.into(), offset, len);
460                Ok(BooleanArray::new(values, nulls))
461            }
462            Err(buffer) => {
463                let values = BooleanBuffer::new(buffer, offset, len);
464                Err((BooleanArray::new(values, nulls), op))
465            }
466        }
467    }
468
469    /// Apply a bitwise binary operation to this array and `rhs` using u64
470    /// operations, returning a new [`BooleanArray`].
471    ///
472    /// Null buffers are unioned: the result is null where either input is null.
473    ///
474    /// See [`BooleanBuffer::from_bitwise_binary_op`] for details on the operation.
475    ///
476    /// # Panics
477    ///
478    /// Panics if `self` and `rhs` have different lengths.
479    ///
480    /// # Example
481    ///
482    /// ```
483    /// # use arrow_array::BooleanArray;
484    /// let a = BooleanArray::from(vec![true, false, true, true]);
485    /// let b = BooleanArray::from(vec![true, true, false, true]);
486    /// let result = a.bitwise_bin_op(&b, |a, b| a & b);
487    /// assert_eq!(result, BooleanArray::from(vec![true, false, false, true]));
488    /// ```
489    pub fn bitwise_bin_op<F>(&self, rhs: &BooleanArray, op: F) -> BooleanArray
490    where
491        F: FnMut(u64, u64) -> u64,
492    {
493        assert_eq!(self.len(), rhs.len());
494        let nulls = NullBuffer::union(self.nulls(), rhs.nulls());
495        let values = BooleanBuffer::from_bitwise_binary_op(
496            self.values.values(),
497            self.values.offset(),
498            rhs.values.values(),
499            rhs.values.offset(),
500            self.values.len(),
501            op,
502        );
503        BooleanArray::new(values, nulls)
504    }
505
506    /// Try to apply a bitwise binary operation to this array and `rhs` in
507    /// place using u64 operations.
508    ///
509    /// If this array's underlying buffer is uniquely owned, the operation is
510    /// applied in place and `Ok` is returned. If the buffer is shared,
511    /// `Err(self)` is returned so the caller can fall back to
512    /// [`bitwise_bin_op`](Self::bitwise_bin_op).
513    ///
514    /// Null buffers are unioned: the result is null where either input is null.
515    ///
516    /// # Panics
517    ///
518    /// Panics if `self` and `rhs` have different lengths.
519    ///
520    /// # Example
521    ///
522    /// ```
523    /// # use arrow_array::BooleanArray;
524    /// let a = BooleanArray::from(vec![true, false, true, true]);
525    /// let b = BooleanArray::from(vec![true, true, false, true]);
526    /// let result = a.bitwise_bin_op_mut(&b, |a, b| a & b).unwrap();
527    /// assert_eq!(result, BooleanArray::from(vec![true, false, false, true]));
528    /// ```
529    pub fn bitwise_bin_op_mut<F>(
530        self,
531        rhs: &BooleanArray,
532        op: F,
533    ) -> Result<BooleanArray, BooleanArray>
534    where
535        F: FnMut(u64, u64) -> u64,
536    {
537        self.try_bitwise_bin_op_in_place(rhs, op)
538            .map_err(|(array, _op)| array)
539    }
540
541    /// Apply a bitwise binary operation to this array and `rhs` in place if the
542    /// buffer is uniquely owned, or clone and apply if shared.
543    ///
544    /// This is a convenience wrapper around [`bitwise_bin_op_mut`](Self::bitwise_bin_op_mut)
545    /// that falls back to [`bitwise_bin_op`](Self::bitwise_bin_op) when the buffer is shared.
546    ///
547    /// Null buffers are unioned: the result is null where either input is null.
548    ///
549    /// # Panics
550    ///
551    /// Panics if `self` and `rhs` have different lengths.
552    ///
553    /// # Example
554    ///
555    /// ```
556    /// # use arrow_array::BooleanArray;
557    /// let a = BooleanArray::from(vec![true, false, true, true]);
558    /// let b = BooleanArray::from(vec![true, true, false, true]);
559    /// let result = a.bitwise_bin_op_mut_or_clone(&b, |a, b| a & b);
560    /// assert_eq!(result, BooleanArray::from(vec![true, false, false, true]));
561    /// ```
562    pub fn bitwise_bin_op_mut_or_clone<F>(self, rhs: &BooleanArray, op: F) -> BooleanArray
563    where
564        F: FnMut(u64, u64) -> u64,
565    {
566        match self.try_bitwise_bin_op_in_place(rhs, op) {
567            Ok(array) => array,
568            Err((array, op)) => array.bitwise_bin_op(rhs, op),
569        }
570    }
571
572    /// Try to apply a binary op in place. Returns `op` back on failure so
573    /// callers can fall back to an allocating path without requiring `F: Clone`.
574    fn try_bitwise_bin_op_in_place<F>(
575        self,
576        rhs: &BooleanArray,
577        op: F,
578    ) -> Result<BooleanArray, (BooleanArray, F)>
579    where
580        F: FnMut(u64, u64) -> u64,
581    {
582        assert_eq!(self.len(), rhs.len());
583        let (values, nulls) = self.into_parts();
584        let offset = values.offset();
585        let len = values.len();
586        let buffer = values.into_inner();
587        match buffer.into_mutable() {
588            Ok(mut buf) => {
589                bit_util::apply_bitwise_binary_op(
590                    buf.as_slice_mut(),
591                    offset,
592                    rhs.values.inner(),
593                    rhs.values.offset(),
594                    len,
595                    op,
596                );
597                // Defer null union to the success path so the Err path returns
598                // self's original nulls, avoiding a redundant union in callers
599                // that fall back to bitwise_bin_op.
600                let nulls = NullBuffer::union(nulls.as_ref(), rhs.nulls());
601                let values = BooleanBuffer::new(buf.into(), offset, len);
602                Ok(BooleanArray::new(values, nulls))
603            }
604            Err(buffer) => {
605                let values = BooleanBuffer::new(buffer, offset, len);
606                Err((BooleanArray::new(values, nulls), op))
607            }
608        }
609    }
610
611    /// Deconstruct this array into its constituent parts
612    pub fn into_parts(self) -> (BooleanBuffer, Option<NullBuffer>) {
613        (self.values, self.nulls)
614    }
615}
616
617/// SAFETY: Correctly implements the contract of Arrow Arrays
618unsafe impl Array for BooleanArray {
619    fn as_any(&self) -> &dyn Any {
620        self
621    }
622
623    fn to_data(&self) -> ArrayData {
624        self.clone().into()
625    }
626
627    fn into_data(self) -> ArrayData {
628        self.into()
629    }
630
631    fn data_type(&self) -> &DataType {
632        &DataType::Boolean
633    }
634
635    fn slice(&self, offset: usize, length: usize) -> ArrayRef {
636        Arc::new(self.slice(offset, length))
637    }
638
639    fn len(&self) -> usize {
640        self.values.len()
641    }
642
643    fn is_empty(&self) -> bool {
644        self.values.is_empty()
645    }
646
647    fn shrink_to_fit(&mut self) {
648        self.values.shrink_to_fit();
649        if let Some(nulls) = &mut self.nulls {
650            nulls.shrink_to_fit();
651        }
652    }
653
654    fn offset(&self) -> usize {
655        self.values.offset()
656    }
657
658    fn nulls(&self) -> Option<&NullBuffer> {
659        self.nulls.as_ref()
660    }
661
662    fn logical_null_count(&self) -> usize {
663        self.null_count()
664    }
665
666    fn get_buffer_memory_size(&self) -> usize {
667        let mut sum = self.values.inner().capacity();
668        if let Some(x) = &self.nulls {
669            sum += x.buffer().capacity()
670        }
671        sum
672    }
673
674    fn get_array_memory_size(&self) -> usize {
675        std::mem::size_of::<Self>() + self.get_buffer_memory_size()
676    }
677
678    #[cfg(feature = "pool")]
679    fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
680        self.values.claim(pool);
681        if let Some(nulls) = &self.nulls {
682            nulls.claim(pool);
683        }
684    }
685}
686
687impl ArrayAccessor for &BooleanArray {
688    type Item = bool;
689
690    fn value(&self, index: usize) -> Self::Item {
691        BooleanArray::value(self, index)
692    }
693
694    unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
695        unsafe { BooleanArray::value_unchecked(self, index) }
696    }
697}
698
699impl From<Vec<bool>> for BooleanArray {
700    fn from(data: Vec<bool>) -> Self {
701        let mut mut_buf = MutableBuffer::new_null(data.len());
702        {
703            let mut_slice = mut_buf.as_slice_mut();
704            for (i, b) in data.iter().enumerate() {
705                if *b {
706                    bit_util::set_bit(mut_slice, i);
707                }
708            }
709        }
710        let array_data = ArrayData::builder(DataType::Boolean)
711            .len(data.len())
712            .add_buffer(mut_buf.into());
713
714        let array_data = unsafe { array_data.build_unchecked() };
715        BooleanArray::from(array_data)
716    }
717}
718
719impl From<Vec<Option<bool>>> for BooleanArray {
720    fn from(data: Vec<Option<bool>>) -> Self {
721        data.iter().collect()
722    }
723}
724
725impl From<ArrayData> for BooleanArray {
726    fn from(data: ArrayData) -> Self {
727        let (data_type, len, nulls, offset, mut buffers, _child_data) = data.into_parts();
728        assert_eq!(
729            data_type,
730            DataType::Boolean,
731            "BooleanArray expected ArrayData with type Boolean got {data_type:?}",
732        );
733        assert_eq!(
734            buffers.len(),
735            1,
736            "BooleanArray data should contain a single buffer only (values buffer)"
737        );
738        let buffer = buffers.pop().expect("checked above");
739        let values = BooleanBuffer::new(buffer, offset, len);
740
741        Self { values, nulls }
742    }
743}
744
745impl From<BooleanArray> for ArrayData {
746    fn from(array: BooleanArray) -> Self {
747        let builder = ArrayDataBuilder::new(DataType::Boolean)
748            .len(array.values.len())
749            .offset(array.values.offset())
750            .nulls(array.nulls)
751            .buffers(vec![array.values.into_inner()]);
752
753        unsafe { builder.build_unchecked() }
754    }
755}
756
757impl<'a> IntoIterator for &'a BooleanArray {
758    type Item = Option<bool>;
759    type IntoIter = BooleanIter<'a>;
760
761    fn into_iter(self) -> Self::IntoIter {
762        BooleanIter::<'a>::new(self)
763    }
764}
765
766impl<'a> BooleanArray {
767    /// constructs a new iterator
768    pub fn iter(&'a self) -> BooleanIter<'a> {
769        BooleanIter::<'a>::new(self)
770    }
771}
772
773/// An optional boolean value
774///
775/// This struct is used as an adapter when creating `BooleanArray` from an iterator.
776/// `FromIterator` for `BooleanArray` takes an iterator where the elements can be `into`
777/// this struct. So once implementing `From` or `Into` trait for a type, an iterator of
778/// the type can be collected to `BooleanArray`.
779///
780/// See also [NativeAdapter](crate::array::NativeAdapter).
781#[derive(Debug)]
782struct BooleanAdapter {
783    /// Corresponding Rust native type if available
784    pub native: Option<bool>,
785}
786
787impl From<bool> for BooleanAdapter {
788    fn from(value: bool) -> Self {
789        BooleanAdapter {
790            native: Some(value),
791        }
792    }
793}
794
795impl From<&bool> for BooleanAdapter {
796    fn from(value: &bool) -> Self {
797        BooleanAdapter {
798            native: Some(*value),
799        }
800    }
801}
802
803impl From<Option<bool>> for BooleanAdapter {
804    fn from(value: Option<bool>) -> Self {
805        BooleanAdapter { native: value }
806    }
807}
808
809impl From<&Option<bool>> for BooleanAdapter {
810    fn from(value: &Option<bool>) -> Self {
811        BooleanAdapter { native: *value }
812    }
813}
814
815impl<Ptr: Into<BooleanAdapter>> FromIterator<Ptr> for BooleanArray {
816    fn from_iter<I: IntoIterator<Item = Ptr>>(iter: I) -> Self {
817        let iter = iter.into_iter();
818        let capacity = match iter.size_hint() {
819            (lower, Some(upper)) if lower == upper => lower,
820            _ => 0,
821        };
822        let mut builder = BooleanBuilder::with_capacity(capacity);
823        builder.extend(iter.map(|item| item.into().native));
824        builder.finish()
825    }
826}
827
828impl BooleanArray {
829    /// Creates a [`BooleanArray`] from an iterator of trusted length.
830    ///
831    /// # Safety
832    ///
833    /// The iterator must be [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html).
834    /// I.e. that `size_hint().1` correctly reports its length. Note that this is a stronger
835    /// guarantee that `ExactSizeIterator` provides which could still report a wrong length.
836    ///
837    /// # Panics
838    ///
839    /// Panics if the iterator does not report an upper bound on `size_hint()`.
840    #[inline]
841    #[allow(
842        private_bounds,
843        reason = "We will expose BooleanAdapter if there is a need"
844    )]
845    pub unsafe fn from_trusted_len_iter<I, P>(iter: I) -> Self
846    where
847        P: Into<BooleanAdapter>,
848        I: ExactSizeIterator<Item = P>,
849    {
850        let data_len = iter.len();
851
852        let num_bytes = bit_util::ceil(data_len, 8);
853        let mut null_builder = MutableBuffer::from_len_zeroed(num_bytes);
854        let mut val_builder = MutableBuffer::from_len_zeroed(num_bytes);
855
856        let data = val_builder.as_slice_mut();
857
858        let null_slice = null_builder.as_slice_mut();
859        iter.enumerate().for_each(|(i, item)| {
860            if let Some(a) = item.into().native {
861                unsafe {
862                    // SAFETY: There will be enough space in the buffers due to the trusted len size
863                    // hint
864                    bit_util::set_bit_raw(null_slice.as_mut_ptr(), i);
865                    if a {
866                        bit_util::set_bit_raw(data.as_mut_ptr(), i);
867                    }
868                }
869            }
870        });
871
872        let values = BooleanBuffer::new(val_builder.into(), 0, data_len);
873        let nulls = NullBuffer::from_unsliced_buffer(null_builder, data_len);
874        BooleanArray::new(values, nulls)
875    }
876}
877
878impl From<BooleanBuffer> for BooleanArray {
879    fn from(values: BooleanBuffer) -> Self {
880        Self {
881            values,
882            nulls: None,
883        }
884    }
885}
886
887#[cfg(test)]
888mod tests {
889    use super::*;
890
891    // Captures the values-buffer identity for a BooleanArray so tests can assert
892    // whether an operation reused the original allocation or produced a new one.
893    struct PointerInfo {
894        ptr: *const u8,
895        offset: usize,
896        len: usize,
897    }
898
899    impl PointerInfo {
900        // Record the current values buffer pointer plus bit offset/length. The
901        // offset/length checks ensure a logically equivalent slice wasn't rebuilt
902        // with a different view over the same allocation.
903        fn new(array: &BooleanArray) -> Self {
904            Self {
905                ptr: array.values().inner().as_ptr(),
906                offset: array.values().offset(),
907                len: array.values().len(),
908            }
909        }
910
911        // Assert that the array still points at the exact same values buffer and
912        // preserves the same bit view.
913        fn assert_same(&self, array: &BooleanArray) {
914            assert_eq!(array.values().inner().as_ptr(), self.ptr);
915            assert_eq!(array.values().offset(), self.offset);
916            assert_eq!(array.values().len(), self.len);
917        }
918
919        // Assert that the array now points at a different values allocation,
920        // indicating the operation fell back to an allocating path.
921        fn assert_different(&self, array: &BooleanArray) {
922            assert_ne!(array.values().inner().as_ptr(), self.ptr);
923        }
924    }
925    use arrow_buffer::Buffer;
926    use rand::{Rng, rng};
927
928    #[test]
929    fn test_boolean_fmt_debug() {
930        let arr = BooleanArray::from(vec![true, false, false]);
931        assert_eq!(
932            "BooleanArray\n[\n  true,\n  false,\n  false,\n]",
933            format!("{arr:?}")
934        );
935    }
936
937    #[test]
938    fn test_boolean_with_null_fmt_debug() {
939        let mut builder = BooleanArray::builder(3);
940        builder.append_value(true);
941        builder.append_null();
942        builder.append_value(false);
943        let arr = builder.finish();
944        assert_eq!(
945            "BooleanArray\n[\n  true,\n  null,\n  false,\n]",
946            format!("{arr:?}")
947        );
948    }
949
950    #[test]
951    fn test_boolean_array_from_vec() {
952        let buf = Buffer::from([10_u8]);
953        let arr = BooleanArray::from(vec![false, true, false, true]);
954        assert_eq!(&buf, arr.values().inner());
955        assert_eq!(4, arr.len());
956        assert_eq!(0, arr.offset());
957        assert_eq!(0, arr.null_count());
958        for i in 0..4 {
959            assert!(!arr.is_null(i));
960            assert!(arr.is_valid(i));
961            assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
962        }
963    }
964
965    #[test]
966    fn test_boolean_array_from_vec_option() {
967        let buf = Buffer::from([10_u8]);
968        let arr = BooleanArray::from(vec![Some(false), Some(true), None, Some(true)]);
969        assert_eq!(&buf, arr.values().inner());
970        assert_eq!(4, arr.len());
971        assert_eq!(0, arr.offset());
972        assert_eq!(1, arr.null_count());
973        for i in 0..4 {
974            if i == 2 {
975                assert!(arr.is_null(i));
976                assert!(!arr.is_valid(i));
977            } else {
978                assert!(!arr.is_null(i));
979                assert!(arr.is_valid(i));
980                assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
981            }
982        }
983    }
984
985    #[test]
986    fn test_boolean_array_from_packed() {
987        let v = [1_u8, 2_u8, 3_u8];
988        let arr = BooleanArray::new_from_packed(v, 0, 24);
989        assert_eq!(24, arr.len());
990        assert_eq!(0, arr.offset());
991        assert_eq!(0, arr.null_count());
992        assert!(arr.nulls.is_none());
993        for i in 0..24 {
994            assert!(!arr.is_null(i));
995            assert!(arr.is_valid(i));
996            assert_eq!(
997                i == 0 || i == 9 || i == 16 || i == 17,
998                arr.value(i),
999                "failed t {i}"
1000            )
1001        }
1002    }
1003
1004    #[test]
1005    fn test_boolean_array_from_slice_u8() {
1006        let v: Vec<u8> = vec![1, 2, 3];
1007        let slice = &v[..];
1008        let arr = BooleanArray::new_from_u8(slice);
1009        assert_eq!(24, arr.len());
1010        assert_eq!(0, arr.offset());
1011        assert_eq!(0, arr.null_count());
1012        assert!(arr.nulls().is_none());
1013        for i in 0..24 {
1014            assert!(!arr.is_null(i));
1015            assert!(arr.is_valid(i));
1016            assert_eq!(
1017                i == 0 || i == 9 || i == 16 || i == 17,
1018                arr.value(i),
1019                "failed t {i}"
1020            )
1021        }
1022    }
1023
1024    #[test]
1025    fn test_boolean_array_from_iter() {
1026        let v = vec![Some(false), Some(true), Some(false), Some(true)];
1027        let arr = v.into_iter().collect::<BooleanArray>();
1028        assert_eq!(4, arr.len());
1029        assert_eq!(0, arr.offset());
1030        assert_eq!(0, arr.null_count());
1031        assert!(arr.nulls().is_none());
1032        for i in 0..3 {
1033            assert!(!arr.is_null(i));
1034            assert!(arr.is_valid(i));
1035            assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
1036        }
1037    }
1038
1039    #[test]
1040    fn test_boolean_array_from_non_nullable_iter() {
1041        let v = vec![true, false, true];
1042        let arr = v.into_iter().collect::<BooleanArray>();
1043        assert_eq!(3, arr.len());
1044        assert_eq!(0, arr.offset());
1045        assert_eq!(0, arr.null_count());
1046        assert!(arr.nulls().is_none());
1047
1048        assert!(arr.value(0));
1049        assert!(!arr.value(1));
1050        assert!(arr.value(2));
1051    }
1052
1053    #[test]
1054    fn test_boolean_array_from_nullable_iter() {
1055        let v = vec![Some(true), None, Some(false), None];
1056        let arr = v.into_iter().collect::<BooleanArray>();
1057        assert_eq!(4, arr.len());
1058        assert_eq!(0, arr.offset());
1059        assert_eq!(2, arr.null_count());
1060        assert!(arr.nulls().is_some());
1061
1062        assert!(arr.is_valid(0));
1063        assert!(arr.is_null(1));
1064        assert!(arr.is_valid(2));
1065        assert!(arr.is_null(3));
1066
1067        assert!(arr.value(0));
1068        assert!(!arr.value(2));
1069    }
1070
1071    #[test]
1072    fn test_boolean_array_from_nullable_trusted_len_iter() {
1073        // Should exhibit the same behavior as `from_iter`, which is tested above.
1074        let v = vec![Some(true), None, Some(false), None];
1075        let expected = v.clone().into_iter().collect::<BooleanArray>();
1076        let actual = unsafe {
1077            // SAFETY: `v` has trusted length
1078            BooleanArray::from_trusted_len_iter(v.into_iter())
1079        };
1080        assert_eq!(expected, actual);
1081    }
1082
1083    #[test]
1084    fn test_boolean_array_from_iter_with_larger_upper_bound() {
1085        // See https://github.com/apache/arrow-rs/issues/8505
1086        // This returns an upper size hint of 4
1087        let iterator = vec![Some(true), None, Some(false), None]
1088            .into_iter()
1089            .filter(Option::is_some);
1090        let arr = iterator.collect::<BooleanArray>();
1091        assert_eq!(2, arr.len());
1092    }
1093
1094    #[test]
1095    fn test_boolean_array_builder() {
1096        // Test building a boolean array with ArrayData builder and offset
1097        // 000011011
1098        let buf = Buffer::from([27_u8]);
1099        let buf2 = buf.clone();
1100        let data = ArrayData::builder(DataType::Boolean)
1101            .len(5)
1102            .offset(2)
1103            .add_buffer(buf)
1104            .build()
1105            .unwrap();
1106        let arr = BooleanArray::from(data);
1107        assert_eq!(&buf2, arr.values().inner());
1108        assert_eq!(5, arr.len());
1109        assert_eq!(2, arr.offset());
1110        assert_eq!(0, arr.null_count());
1111        for i in 0..3 {
1112            assert_eq!(i != 0, arr.value(i), "failed at {i}");
1113        }
1114    }
1115
1116    #[test]
1117    #[should_panic(
1118        expected = "Trying to access an element at index 4 from a BooleanArray of length 3"
1119    )]
1120    fn test_fixed_size_binary_array_get_value_index_out_of_bound() {
1121        let v = vec![Some(true), None, Some(false)];
1122        let array = v.into_iter().collect::<BooleanArray>();
1123
1124        array.value(4);
1125    }
1126
1127    #[test]
1128    #[should_panic(expected = "BooleanArray data should contain a single buffer only \
1129                               (values buffer)")]
1130    // Different error messages, so skip for now
1131    // https://github.com/apache/arrow-rs/issues/1545
1132    #[cfg(not(feature = "force_validate"))]
1133    fn test_boolean_array_invalid_buffer_len() {
1134        let data = unsafe {
1135            ArrayData::builder(DataType::Boolean)
1136                .len(5)
1137                .build_unchecked()
1138        };
1139        drop(BooleanArray::from(data));
1140    }
1141
1142    #[test]
1143    #[should_panic(expected = "BooleanArray expected ArrayData with type Boolean got Int32")]
1144    fn test_from_array_data_validation() {
1145        let _ = BooleanArray::from(ArrayData::new_empty(&DataType::Int32));
1146    }
1147
1148    #[test]
1149    #[cfg_attr(miri, ignore)] // Takes too long
1150    fn test_true_false_count() {
1151        let mut rng = rng();
1152
1153        for _ in 0..10 {
1154            // No nulls
1155            let d: Vec<_> = (0..2000).map(|_| rng.random_bool(0.5)).collect();
1156            let b = BooleanArray::from(d.clone());
1157
1158            let expected_true = d.iter().filter(|x| **x).count();
1159            assert_eq!(b.true_count(), expected_true);
1160            assert_eq!(b.false_count(), d.len() - expected_true);
1161
1162            // With nulls
1163            let d: Vec<_> = (0..2000)
1164                .map(|_| rng.random_bool(0.5).then(|| rng.random_bool(0.5)))
1165                .collect();
1166            let b = BooleanArray::from(d.clone());
1167
1168            let expected_true = d.iter().filter(|x| matches!(x, Some(true))).count();
1169            assert_eq!(b.true_count(), expected_true);
1170
1171            let expected_false = d.iter().filter(|x| matches!(x, Some(false))).count();
1172            assert_eq!(b.false_count(), expected_false);
1173        }
1174    }
1175
1176    #[test]
1177    fn test_into_parts() {
1178        let boolean_array = [Some(true), None, Some(false)]
1179            .into_iter()
1180            .collect::<BooleanArray>();
1181        let (values, nulls) = boolean_array.into_parts();
1182        assert_eq!(values.values(), &[0b0000_0001]);
1183        assert!(nulls.is_some());
1184        assert_eq!(nulls.unwrap().buffer().as_slice(), &[0b0000_0101]);
1185
1186        let boolean_array =
1187            BooleanArray::from(vec![false, false, false, false, false, false, false, true]);
1188        let (values, nulls) = boolean_array.into_parts();
1189        assert_eq!(values.values(), &[0b1000_0000]);
1190        assert!(nulls.is_none());
1191    }
1192
1193    #[test]
1194    fn test_new_null_array() {
1195        let arr = BooleanArray::new_null(5);
1196
1197        assert_eq!(arr.len(), 5);
1198        assert_eq!(arr.null_count(), 5);
1199        assert_eq!(arr.true_count(), 0);
1200        assert_eq!(arr.false_count(), 0);
1201
1202        for i in 0..5 {
1203            assert!(arr.is_null(i));
1204            assert!(!arr.is_valid(i));
1205        }
1206    }
1207
1208    #[test]
1209    fn test_slice_with_nulls() {
1210        let arr = BooleanArray::from(vec![Some(true), None, Some(false)]);
1211        let sliced = arr.slice(1, 2);
1212
1213        assert_eq!(sliced.len(), 2);
1214        assert_eq!(sliced.null_count(), 1);
1215
1216        assert!(sliced.is_null(0));
1217        assert!(sliced.is_valid(1));
1218        assert!(!sliced.value(1));
1219    }
1220
1221    #[test]
1222    fn test_has_true_has_false_all_true() {
1223        let arr = BooleanArray::from(vec![true, true, true]);
1224        assert!(arr.has_true());
1225        assert!(!arr.has_false());
1226    }
1227
1228    #[test]
1229    fn test_has_true_has_false_all_false() {
1230        let arr = BooleanArray::from(vec![false, false, false]);
1231        assert!(!arr.has_true());
1232        assert!(arr.has_false());
1233    }
1234
1235    #[test]
1236    fn test_has_true_has_false_mixed() {
1237        let arr = BooleanArray::from(vec![true, false, true]);
1238        assert!(arr.has_true());
1239        assert!(arr.has_false());
1240    }
1241
1242    #[test]
1243    fn test_has_true_has_false_empty() {
1244        let arr = BooleanArray::from(Vec::<bool>::new());
1245        assert!(!arr.has_true());
1246        assert!(!arr.has_false());
1247    }
1248
1249    #[test]
1250    fn test_has_true_has_false_nulls_all_valid_true() {
1251        let arr = BooleanArray::from(vec![Some(true), None, Some(true)]);
1252        assert!(arr.has_true());
1253        assert!(!arr.has_false());
1254    }
1255
1256    #[test]
1257    fn test_has_true_has_false_nulls_all_valid_false() {
1258        let arr = BooleanArray::from(vec![Some(false), None, Some(false)]);
1259        assert!(!arr.has_true());
1260        assert!(arr.has_false());
1261    }
1262
1263    #[test]
1264    fn test_has_true_has_false_all_null() {
1265        let arr = BooleanArray::new_null(5);
1266        assert!(!arr.has_true());
1267        assert!(!arr.has_false());
1268    }
1269
1270    #[test]
1271    fn test_has_false_aligned_suffix_all_true() {
1272        let arr = BooleanArray::from(vec![true; 129]);
1273        assert!(arr.has_true());
1274        assert!(!arr.has_false());
1275    }
1276
1277    #[test]
1278    fn test_has_false_non_aligned_all_true() {
1279        // 65 elements: exercises the remainder path in has_false
1280        let arr = BooleanArray::from(vec![true; 65]);
1281        assert!(arr.has_true());
1282        assert!(!arr.has_false());
1283    }
1284
1285    #[test]
1286    fn test_has_false_non_aligned_last_false() {
1287        // 64 trues + 1 false: remainder path should find the false
1288        let mut values = vec![true; 64];
1289        values.push(false);
1290        let arr = BooleanArray::from(values);
1291        assert!(arr.has_true());
1292        assert!(arr.has_false());
1293    }
1294
1295    #[test]
1296    fn test_has_false_exact_64_all_true() {
1297        // Exactly 64 elements, no remainder
1298        let arr = BooleanArray::from(vec![true; 64]);
1299        assert!(arr.has_true());
1300        assert!(!arr.has_false());
1301    }
1302
1303    #[test]
1304    fn test_has_true_has_false_unaligned_slices() {
1305        let cases = [
1306            (1, 129, true, false),
1307            (3, 130, true, false),
1308            (5, 65, true, false),
1309            (7, 64, true, false),
1310        ];
1311
1312        let base = BooleanArray::from(vec![true; 300]);
1313
1314        for (offset, len, expected_has_true, expected_has_false) in cases {
1315            let arr = base.slice(offset, len);
1316            assert_eq!(
1317                arr.has_true(),
1318                expected_has_true,
1319                "offset={offset} len={len}"
1320            );
1321            assert_eq!(
1322                arr.has_false(),
1323                expected_has_false,
1324                "offset={offset} len={len}"
1325            );
1326        }
1327    }
1328
1329    #[test]
1330    fn test_has_true_has_false_exact_multiples_of_64() {
1331        let cases = [
1332            (64, true, false),
1333            (128, true, false),
1334            (192, true, false),
1335            (256, true, false),
1336        ];
1337
1338        for (len, expected_has_true, expected_has_false) in cases {
1339            let arr = BooleanArray::from(vec![true; len]);
1340            assert_eq!(arr.has_true(), expected_has_true, "len={len}");
1341            assert_eq!(arr.has_false(), expected_has_false, "len={len}");
1342        }
1343    }
1344
1345    #[test]
1346    fn test_bitwise_unary_not() {
1347        let arr = BooleanArray::from(vec![true, false, true, false]);
1348        let result = arr.bitwise_unary(|x| !x);
1349        let expected = BooleanArray::from(vec![false, true, false, true]);
1350        assert_eq!(result, expected);
1351    }
1352
1353    #[test]
1354    fn test_bitwise_unary_preserves_nulls() {
1355        let arr = BooleanArray::from(vec![Some(true), None, Some(false), Some(true)]);
1356        let result = arr.bitwise_unary(|x| !x);
1357
1358        assert_eq!(result.null_count(), 1);
1359        assert!(result.is_null(1));
1360        assert!(!result.value(0));
1361        assert!(result.value(2));
1362        assert!(!result.value(3));
1363    }
1364
1365    #[test]
1366    fn test_bitwise_unary_mut_unshared() {
1367        let arr = BooleanArray::from(vec![true, false, true, false]);
1368        let info = PointerInfo::new(&arr);
1369        let result = arr.bitwise_unary_mut(|x| !x).unwrap();
1370        let expected = BooleanArray::from(vec![false, true, false, true]);
1371        assert_eq!(result, expected);
1372        info.assert_same(&result);
1373    }
1374
1375    #[test]
1376    fn test_bitwise_unary_mut_shared() {
1377        let arr = BooleanArray::from(vec![true, false, true, false]);
1378        let info = PointerInfo::new(&arr);
1379        let _shared = arr.clone();
1380        let result = arr.bitwise_unary_mut(|x| !x);
1381        assert!(result.is_err());
1382
1383        let returned = result.unwrap_err();
1384        assert_eq!(returned, BooleanArray::from(vec![true, false, true, false]));
1385        info.assert_same(&returned);
1386    }
1387
1388    #[test]
1389    fn test_bitwise_unary_mut_with_nulls() {
1390        let arr = BooleanArray::from(vec![Some(true), None, Some(false)]);
1391        let result = arr.bitwise_unary_mut(|x| !x).unwrap();
1392
1393        assert_eq!(result.null_count(), 1);
1394        assert!(result.is_null(1));
1395        assert!(!result.value(0));
1396        assert!(result.value(2));
1397    }
1398
1399    #[test]
1400    fn test_bitwise_unary_mut_or_clone_shared() {
1401        let arr = BooleanArray::from(vec![true, false, true]);
1402        let info = PointerInfo::new(&arr);
1403        let _shared = arr.clone();
1404        let result = arr.bitwise_unary_mut_or_clone(|x| !x);
1405        assert_eq!(result, BooleanArray::from(vec![false, true, false]));
1406        info.assert_different(&result);
1407    }
1408
1409    #[test]
1410    fn test_bitwise_unary_mut_or_clone_unshared() {
1411        // Covers the uniquely-owned fast path in bitwise_unary_mut_or_clone.
1412        let arr = BooleanArray::from(vec![true, false, true]);
1413        let info = PointerInfo::new(&arr);
1414        let result = arr.bitwise_unary_mut_or_clone(|x| !x);
1415        assert_eq!(result, BooleanArray::from(vec![false, true, false]));
1416        info.assert_same(&result);
1417    }
1418
1419    #[test]
1420    fn test_bitwise_bin_op_and() {
1421        let a = BooleanArray::from(vec![true, false, true, true]);
1422        let b = BooleanArray::from(vec![true, true, false, true]);
1423        let result = a.bitwise_bin_op(&b, |a, b| a & b);
1424        assert_eq!(result, BooleanArray::from(vec![true, false, false, true]));
1425    }
1426
1427    #[test]
1428    fn test_bitwise_bin_op_or() {
1429        let a = BooleanArray::from(vec![true, false, true, false]);
1430        let b = BooleanArray::from(vec![false, true, false, false]);
1431        let result = a.bitwise_bin_op(&b, |a, b| a | b);
1432        assert_eq!(result, BooleanArray::from(vec![true, true, true, false]));
1433    }
1434
1435    #[test]
1436    fn test_bitwise_bin_op_null_union() {
1437        let a = BooleanArray::from(vec![Some(true), None, Some(true), Some(false)]);
1438        let b = BooleanArray::from(vec![Some(true), Some(true), None, Some(true)]);
1439        let result = a.bitwise_bin_op(&b, |a, b| a & b);
1440
1441        assert_eq!(result.null_count(), 2);
1442        assert!(result.is_null(1));
1443        assert!(result.is_null(2));
1444        assert!(result.value(0));
1445        assert!(!result.value(3));
1446    }
1447
1448    #[test]
1449    fn test_bitwise_bin_op_one_nullable() {
1450        let a = BooleanArray::from(vec![Some(true), None, Some(true)]);
1451        let b = BooleanArray::from(vec![false, true, true]);
1452        let result = a.bitwise_bin_op(&b, |a, b| a & b);
1453
1454        assert_eq!(result.null_count(), 1);
1455        assert!(result.is_null(1));
1456        assert!(!result.value(0));
1457        assert!(result.value(2));
1458    }
1459
1460    #[test]
1461    fn test_bitwise_bin_op_no_nulls() {
1462        let a = BooleanArray::from(vec![true, false, true]);
1463        let b = BooleanArray::from(vec![false, true, true]);
1464        let result = a.bitwise_bin_op(&b, |a, b| a | b);
1465
1466        assert!(result.nulls().is_none());
1467        assert_eq!(result, BooleanArray::from(vec![true, true, true]));
1468    }
1469
1470    #[test]
1471    fn test_bitwise_bin_op_mut_unshared() {
1472        let a = BooleanArray::from(vec![true, false, true, true]);
1473        let info = PointerInfo::new(&a);
1474        let b = BooleanArray::from(vec![true, true, false, true]);
1475        let result = a.bitwise_bin_op_mut(&b, |a, b| a & b).unwrap();
1476        assert_eq!(result, BooleanArray::from(vec![true, false, false, true]));
1477        info.assert_same(&result);
1478    }
1479
1480    #[test]
1481    fn test_bitwise_bin_op_mut_shared() {
1482        let a = BooleanArray::from(vec![true, false, true, true]);
1483        let info = PointerInfo::new(&a);
1484        let _shared = a.clone();
1485        let result = a.bitwise_bin_op_mut(
1486            &BooleanArray::from(vec![true, true, false, true]),
1487            |a, b| a & b,
1488        );
1489        assert!(result.is_err());
1490        let returned = result.unwrap_err();
1491        info.assert_same(&returned);
1492    }
1493
1494    #[test]
1495    fn test_bitwise_bin_op_mut_with_nulls() {
1496        let a = BooleanArray::from(vec![Some(true), None, Some(true), Some(false)]);
1497        let b = BooleanArray::from(vec![Some(true), Some(true), None, Some(true)]);
1498        let result = a.bitwise_bin_op_mut(&b, |a, b| a & b).unwrap();
1499
1500        assert_eq!(result.null_count(), 2);
1501        assert!(result.is_null(1));
1502        assert!(result.is_null(2));
1503        assert!(result.value(0));
1504        assert!(!result.value(3));
1505    }
1506
1507    #[test]
1508    fn test_bitwise_bin_op_mut_or_clone_shared() {
1509        let a = BooleanArray::from(vec![true, false, true, true]);
1510        let info = PointerInfo::new(&a);
1511        let _shared = a.clone();
1512        let b = BooleanArray::from(vec![true, true, false, true]);
1513        let result = a.bitwise_bin_op_mut_or_clone(&b, |a, b| a & b);
1514        assert_eq!(result, BooleanArray::from(vec![true, false, false, true]));
1515        info.assert_different(&result);
1516    }
1517
1518    #[test]
1519    fn test_bitwise_bin_op_mut_or_clone_shared_with_nulls() {
1520        // When the buffer is shared, _mut_or_clone falls back to bitwise_bin_op.
1521        // The null union must only be applied once, not double-applied.
1522        let a = BooleanArray::from(vec![Some(true), None, Some(true), Some(false)]);
1523        let info = PointerInfo::new(&a);
1524        let _shared = a.clone();
1525        let b = BooleanArray::from(vec![Some(true), Some(true), None, Some(true)]);
1526
1527        let expected = a.bitwise_bin_op(&b, |a, b| a & b);
1528        let result = a.bitwise_bin_op_mut_or_clone(&b, |a, b| a & b);
1529
1530        assert_eq!(result, expected);
1531        assert_eq!(result.null_count(), 2);
1532        assert!(result.is_null(1));
1533        assert!(result.is_null(2));
1534        info.assert_different(&result);
1535    }
1536
1537    #[test]
1538    fn test_bitwise_bin_op_mut_or_clone_unshared_with_nulls() {
1539        // Covers the uniquely-owned fast path in bitwise_bin_op_mut_or_clone,
1540        // including null union on the in-place path.
1541        let a = BooleanArray::from(vec![Some(true), None, Some(true), Some(false)]);
1542        let info = PointerInfo::new(&a);
1543        let b = BooleanArray::from(vec![Some(true), Some(true), None, Some(true)]);
1544        let result = a.bitwise_bin_op_mut_or_clone(&b, |a, b| a & b);
1545
1546        assert_eq!(result.null_count(), 2);
1547        assert!(result.is_null(1));
1548        assert!(result.is_null(2));
1549        assert!(result.value(0));
1550        assert!(!result.value(3));
1551        info.assert_same(&result);
1552    }
1553
1554    #[test]
1555    fn test_bitwise_unary_empty() {
1556        let arr = BooleanArray::from(Vec::<bool>::new());
1557        let result = arr.bitwise_unary(|x| !x);
1558        assert_eq!(result.len(), 0);
1559    }
1560
1561    #[test]
1562    fn test_bitwise_bin_op_empty() {
1563        let a = BooleanArray::from(Vec::<bool>::new());
1564        let b = BooleanArray::from(Vec::<bool>::new());
1565        let result = a.bitwise_bin_op(&b, |a, b| a & b);
1566        assert_eq!(result.len(), 0);
1567    }
1568
1569    #[test]
1570    fn test_bitwise_unary_sliced() {
1571        // Slicing creates a non-zero offset into the underlying buffer.
1572        let arr = BooleanArray::from(vec![true, false, true, true, false]);
1573        let sliced = arr.slice(1, 3); // [false, true, true]
1574
1575        let result = sliced.bitwise_unary(|x| !x);
1576        assert_eq!(result.len(), 3);
1577        assert!(result.value(0));
1578        assert!(!result.value(1));
1579        assert!(!result.value(2));
1580    }
1581
1582    #[test]
1583    fn test_bitwise_unary_mut_sliced() {
1584        // Slicing shares the buffer, so _mut must return Err.
1585        let arr = BooleanArray::from(vec![true, false, true, true, false]);
1586        let sliced = arr.slice(1, 3);
1587        assert!(sliced.bitwise_unary_mut(|x| !x).is_err());
1588    }
1589
1590    #[test]
1591    fn test_bitwise_unary_mut_or_clone_sliced() {
1592        // Slicing shares the buffer, so _mut_or_clone falls back to allocating.
1593        let arr = BooleanArray::from(vec![true, false, true, true, false]);
1594        let sliced = arr.slice(1, 3); // [false, true, true]
1595
1596        let result = sliced.bitwise_unary_mut_or_clone(|x| !x);
1597        assert_eq!(result.len(), 3);
1598        assert!(result.value(0));
1599        assert!(!result.value(1));
1600        assert!(!result.value(2));
1601    }
1602
1603    #[test]
1604    fn test_bitwise_bin_op_different_offsets() {
1605        // Left and right sliced to different offsets exercises misaligned
1606        // bit handling in from_bitwise_binary_op.
1607        let left_full = BooleanArray::from(vec![false, true, false, true, true]);
1608        let right_full = BooleanArray::from(vec![true, true, true, false, true, false]);
1609
1610        let left = left_full.slice(1, 3); // [true, false, true]
1611        let right = right_full.slice(2, 3); // [true, false, true]
1612
1613        let result = left.bitwise_bin_op(&right, |a, b| a & b);
1614        assert_eq!(result.len(), 3);
1615        assert!(result.value(0));
1616        assert!(!result.value(1));
1617        assert!(result.value(2));
1618    }
1619
1620    #[test]
1621    fn test_bitwise_bin_op_mut_or_clone_different_offsets() {
1622        // Both sliced (shared buffers), so falls back to allocating path.
1623        let left_full = BooleanArray::from(vec![false, true, true, false, true]);
1624        let right_full = BooleanArray::from(vec![true, true, false, false, true, false]);
1625
1626        let left = left_full.slice(1, 3); // [true, true, false]
1627        let right = right_full.slice(2, 3); // [false, false, true]
1628
1629        let expected = left.bitwise_bin_op(&right, |a, b| a & b);
1630        let result = left.bitwise_bin_op_mut_or_clone(&right, |a, b| a & b);
1631        assert_eq!(result, expected);
1632    }
1633}