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