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