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