1use crate::array::print_long_array;
19use crate::builder::BooleanBuilder;
20use crate::iterator::BooleanIter;
21use crate::{Array, ArrayAccessor, ArrayRef, Scalar};
22use arrow_buffer::bit_chunk_iterator::UnalignedBitChunk;
23use arrow_buffer::{BooleanBuffer, Buffer, MutableBuffer, NullBuffer, bit_util};
24use arrow_data::{ArrayData, ArrayDataBuilder};
25use arrow_schema::DataType;
26use std::any::Any;
27use std::sync::Arc;
28
29#[derive(Clone)]
69pub struct BooleanArray {
70 values: BooleanBuffer,
71 nulls: Option<NullBuffer>,
72}
73
74impl std::fmt::Debug for BooleanArray {
75 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
76 write!(f, "BooleanArray\n[\n")?;
77 print_long_array(self, f, |array, index, f| {
78 std::fmt::Debug::fmt(&array.value(index), f)
79 })?;
80 write!(f, "]")
81 }
82}
83
84impl BooleanArray {
85 pub fn new(values: BooleanBuffer, nulls: Option<NullBuffer>) -> Self {
91 if let Some(n) = nulls.as_ref() {
92 assert_eq!(values.len(), n.len());
93 }
94 Self { values, nulls }
95 }
96
97 pub fn new_null(len: usize) -> Self {
99 Self {
100 values: BooleanBuffer::new_unset(len),
101 nulls: Some(NullBuffer::new_null(len)),
102 }
103 }
104
105 pub fn new_scalar(value: bool) -> Scalar<Self> {
107 let values = match value {
108 true => BooleanBuffer::new_set(1),
109 false => BooleanBuffer::new_unset(1),
110 };
111 Scalar::new(Self::new(values, None))
112 }
113
114 pub fn new_from_packed(buffer: impl Into<Buffer>, offset: usize, len: usize) -> Self {
120 BooleanBuffer::new(buffer.into(), offset, len).into()
121 }
122
123 pub fn new_from_u8(value: &[u8]) -> Self {
129 BooleanBuffer::new(Buffer::from(value), 0, value.len() * 8).into()
130 }
131
132 pub fn len(&self) -> usize {
134 self.values.len()
135 }
136
137 pub fn is_empty(&self) -> bool {
139 self.values.is_empty()
140 }
141
142 pub fn slice(&self, offset: usize, length: usize) -> Self {
144 Self {
145 values: self.values.slice(offset, length),
146 nulls: self.nulls.as_ref().map(|n| n.slice(offset, length)),
147 }
148 }
149
150 pub fn builder(capacity: usize) -> BooleanBuilder {
152 BooleanBuilder::with_capacity(capacity)
153 }
154
155 pub fn values(&self) -> &BooleanBuffer {
157 &self.values
158 }
159
160 const CHUNK_FOLD_BLOCK_SIZE: usize = 16;
164
165 fn unaligned_bit_chunks(&self) -> UnalignedBitChunk<'_> {
167 UnalignedBitChunk::new(self.values().values(), self.values().offset(), self.len())
168 }
169
170 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 pub fn false_count(&self) -> usize {
189 self.len() - self.null_count() - self.true_count()
190 }
191
192 pub fn has_true(&self) -> bool {
199 match self.nulls() {
200 Some(nulls) => {
201 let null_chunks = nulls.inner().bit_chunks().iter_padded();
202 let value_chunks = self.values().bit_chunks().iter_padded();
203 null_chunks.zip(value_chunks).any(|(n, v)| (n & v) != 0)
204 }
205 None => {
206 let bit_chunks = self.unaligned_bit_chunks();
207 let chunks = bit_chunks.chunks();
208 let mut exact = chunks.chunks_exact(Self::CHUNK_FOLD_BLOCK_SIZE);
209 let found = bit_chunks.prefix().unwrap_or(0) != 0
210 || exact.any(|block| block.iter().fold(0u64, |acc, &c| acc | c) != 0);
211 found
212 || exact.remainder().iter().any(|&c| c != 0)
213 || bit_chunks.suffix().unwrap_or(0) != 0
214 }
215 }
216 }
217
218 pub fn has_false(&self) -> bool {
225 match self.nulls() {
226 Some(nulls) => {
227 let null_chunks = nulls.inner().bit_chunks().iter_padded();
228 let value_chunks = self.values().bit_chunks().iter_padded();
229 null_chunks.zip(value_chunks).any(|(n, v)| (n & !v) != 0)
230 }
231 None => {
232 let bit_chunks = self.unaligned_bit_chunks();
233 let lead_mask = !((1u64 << bit_chunks.lead_padding()) - 1);
236 let trail_mask = if bit_chunks.trailing_padding() == 0 {
237 u64::MAX
238 } else {
239 (1u64 << (64 - bit_chunks.trailing_padding())) - 1
240 };
241 let (prefix_fill, suffix_fill) = match (bit_chunks.prefix(), bit_chunks.suffix()) {
242 (Some(_), Some(_)) => (!lead_mask, !trail_mask),
243 (Some(_), None) => (!lead_mask | !trail_mask, 0),
244 (None, Some(_)) => (0, !trail_mask),
245 (None, None) => (0, 0),
246 };
247 let chunks = bit_chunks.chunks();
248 let mut exact = chunks.chunks_exact(Self::CHUNK_FOLD_BLOCK_SIZE);
249 let found = bit_chunks
250 .prefix()
251 .is_some_and(|v| (v | prefix_fill) != u64::MAX)
252 || exact
253 .any(|block| block.iter().fold(u64::MAX, |acc, &c| acc & c) != u64::MAX);
254 found
255 || exact.remainder().iter().any(|&c| c != u64::MAX)
256 || bit_chunks
257 .suffix()
258 .is_some_and(|v| (v | suffix_fill) != u64::MAX)
259 }
260 }
261 }
262
263 pub unsafe fn value_unchecked(&self, i: usize) -> bool {
271 unsafe { self.values.value_unchecked(i) }
272 }
273
274 pub fn value(&self, i: usize) -> bool {
282 assert!(
283 i < self.len(),
284 "Trying to access an element at index {} from a BooleanArray of length {}",
285 i,
286 self.len()
287 );
288 unsafe { self.value_unchecked(i) }
291 }
292
293 pub fn take_iter<'a>(
295 &'a self,
296 indexes: impl Iterator<Item = Option<usize>> + 'a,
297 ) -> impl Iterator<Item = Option<bool>> + 'a {
298 indexes.map(|opt_index| opt_index.map(|index| self.value(index)))
299 }
300
301 pub unsafe fn take_iter_unchecked<'a>(
306 &'a self,
307 indexes: impl Iterator<Item = Option<usize>> + 'a,
308 ) -> impl Iterator<Item = Option<bool>> + 'a {
309 indexes.map(|opt_index| opt_index.map(|index| unsafe { self.value_unchecked(index) }))
310 }
311
312 pub fn from_unary<T: ArrayAccessor, F>(left: T, mut op: F) -> Self
323 where
324 F: FnMut(T::Item) -> bool,
325 {
326 let nulls = left.logical_nulls();
327 let values = BooleanBuffer::collect_bool(left.len(), |i| unsafe {
328 op(left.value_unchecked(i))
330 });
331 Self::new(values, nulls)
332 }
333
334 pub fn from_binary<T: ArrayAccessor, S: ArrayAccessor, F>(left: T, right: S, mut op: F) -> Self
351 where
352 F: FnMut(T::Item, S::Item) -> bool,
353 {
354 assert_eq!(left.len(), right.len());
355
356 let nulls = NullBuffer::union(
357 left.logical_nulls().as_ref(),
358 right.logical_nulls().as_ref(),
359 );
360 let values = BooleanBuffer::collect_bool(left.len(), |i| unsafe {
361 op(left.value_unchecked(i), right.value_unchecked(i))
363 });
364 Self::new(values, nulls)
365 }
366
367 pub fn into_parts(self) -> (BooleanBuffer, Option<NullBuffer>) {
369 (self.values, self.nulls)
370 }
371}
372
373unsafe impl Array for BooleanArray {
375 fn as_any(&self) -> &dyn Any {
376 self
377 }
378
379 fn to_data(&self) -> ArrayData {
380 self.clone().into()
381 }
382
383 fn into_data(self) -> ArrayData {
384 self.into()
385 }
386
387 fn data_type(&self) -> &DataType {
388 &DataType::Boolean
389 }
390
391 fn slice(&self, offset: usize, length: usize) -> ArrayRef {
392 Arc::new(self.slice(offset, length))
393 }
394
395 fn len(&self) -> usize {
396 self.values.len()
397 }
398
399 fn is_empty(&self) -> bool {
400 self.values.is_empty()
401 }
402
403 fn shrink_to_fit(&mut self) {
404 self.values.shrink_to_fit();
405 if let Some(nulls) = &mut self.nulls {
406 nulls.shrink_to_fit();
407 }
408 }
409
410 fn offset(&self) -> usize {
411 self.values.offset()
412 }
413
414 fn nulls(&self) -> Option<&NullBuffer> {
415 self.nulls.as_ref()
416 }
417
418 fn logical_null_count(&self) -> usize {
419 self.null_count()
420 }
421
422 fn get_buffer_memory_size(&self) -> usize {
423 let mut sum = self.values.inner().capacity();
424 if let Some(x) = &self.nulls {
425 sum += x.buffer().capacity()
426 }
427 sum
428 }
429
430 fn get_array_memory_size(&self) -> usize {
431 std::mem::size_of::<Self>() + self.get_buffer_memory_size()
432 }
433
434 #[cfg(feature = "pool")]
435 fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
436 self.values.claim(pool);
437 if let Some(nulls) = &self.nulls {
438 nulls.claim(pool);
439 }
440 }
441}
442
443impl ArrayAccessor for &BooleanArray {
444 type Item = bool;
445
446 fn value(&self, index: usize) -> Self::Item {
447 BooleanArray::value(self, index)
448 }
449
450 unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
451 unsafe { BooleanArray::value_unchecked(self, index) }
452 }
453}
454
455impl From<Vec<bool>> for BooleanArray {
456 fn from(data: Vec<bool>) -> Self {
457 let mut mut_buf = MutableBuffer::new_null(data.len());
458 {
459 let mut_slice = mut_buf.as_slice_mut();
460 for (i, b) in data.iter().enumerate() {
461 if *b {
462 bit_util::set_bit(mut_slice, i);
463 }
464 }
465 }
466 let array_data = ArrayData::builder(DataType::Boolean)
467 .len(data.len())
468 .add_buffer(mut_buf.into());
469
470 let array_data = unsafe { array_data.build_unchecked() };
471 BooleanArray::from(array_data)
472 }
473}
474
475impl From<Vec<Option<bool>>> for BooleanArray {
476 fn from(data: Vec<Option<bool>>) -> Self {
477 data.iter().collect()
478 }
479}
480
481impl From<ArrayData> for BooleanArray {
482 fn from(data: ArrayData) -> Self {
483 let (data_type, len, nulls, offset, mut buffers, _child_data) = data.into_parts();
484 assert_eq!(
485 data_type,
486 DataType::Boolean,
487 "BooleanArray expected ArrayData with type Boolean got {data_type:?}",
488 );
489 assert_eq!(
490 buffers.len(),
491 1,
492 "BooleanArray data should contain a single buffer only (values buffer)"
493 );
494 let buffer = buffers.pop().expect("checked above");
495 let values = BooleanBuffer::new(buffer, offset, len);
496
497 Self { values, nulls }
498 }
499}
500
501impl From<BooleanArray> for ArrayData {
502 fn from(array: BooleanArray) -> Self {
503 let builder = ArrayDataBuilder::new(DataType::Boolean)
504 .len(array.values.len())
505 .offset(array.values.offset())
506 .nulls(array.nulls)
507 .buffers(vec![array.values.into_inner()]);
508
509 unsafe { builder.build_unchecked() }
510 }
511}
512
513impl<'a> IntoIterator for &'a BooleanArray {
514 type Item = Option<bool>;
515 type IntoIter = BooleanIter<'a>;
516
517 fn into_iter(self) -> Self::IntoIter {
518 BooleanIter::<'a>::new(self)
519 }
520}
521
522impl<'a> BooleanArray {
523 pub fn iter(&'a self) -> BooleanIter<'a> {
525 BooleanIter::<'a>::new(self)
526 }
527}
528
529#[derive(Debug)]
538struct BooleanAdapter {
539 pub native: Option<bool>,
541}
542
543impl From<bool> for BooleanAdapter {
544 fn from(value: bool) -> Self {
545 BooleanAdapter {
546 native: Some(value),
547 }
548 }
549}
550
551impl From<&bool> for BooleanAdapter {
552 fn from(value: &bool) -> Self {
553 BooleanAdapter {
554 native: Some(*value),
555 }
556 }
557}
558
559impl From<Option<bool>> for BooleanAdapter {
560 fn from(value: Option<bool>) -> Self {
561 BooleanAdapter { native: value }
562 }
563}
564
565impl From<&Option<bool>> for BooleanAdapter {
566 fn from(value: &Option<bool>) -> Self {
567 BooleanAdapter { native: *value }
568 }
569}
570
571impl<Ptr: Into<BooleanAdapter>> FromIterator<Ptr> for BooleanArray {
572 fn from_iter<I: IntoIterator<Item = Ptr>>(iter: I) -> Self {
573 let iter = iter.into_iter();
574 let capacity = match iter.size_hint() {
575 (lower, Some(upper)) if lower == upper => lower,
576 _ => 0,
577 };
578 let mut builder = BooleanBuilder::with_capacity(capacity);
579 builder.extend(iter.map(|item| item.into().native));
580 builder.finish()
581 }
582}
583
584impl BooleanArray {
585 #[inline]
597 #[allow(
598 private_bounds,
599 reason = "We will expose BooleanAdapter if there is a need"
600 )]
601 pub unsafe fn from_trusted_len_iter<I, P>(iter: I) -> Self
602 where
603 P: Into<BooleanAdapter>,
604 I: ExactSizeIterator<Item = P>,
605 {
606 let data_len = iter.len();
607
608 let num_bytes = bit_util::ceil(data_len, 8);
609 let mut null_builder = MutableBuffer::from_len_zeroed(num_bytes);
610 let mut val_builder = MutableBuffer::from_len_zeroed(num_bytes);
611
612 let data = val_builder.as_slice_mut();
613
614 let null_slice = null_builder.as_slice_mut();
615 iter.enumerate().for_each(|(i, item)| {
616 if let Some(a) = item.into().native {
617 unsafe {
618 bit_util::set_bit_raw(null_slice.as_mut_ptr(), i);
621 if a {
622 bit_util::set_bit_raw(data.as_mut_ptr(), i);
623 }
624 }
625 }
626 });
627
628 let values = BooleanBuffer::new(val_builder.into(), 0, data_len);
629 let nulls = NullBuffer::from_unsliced_buffer(null_builder, data_len);
630 BooleanArray::new(values, nulls)
631 }
632}
633
634impl From<BooleanBuffer> for BooleanArray {
635 fn from(values: BooleanBuffer) -> Self {
636 Self {
637 values,
638 nulls: None,
639 }
640 }
641}
642
643#[cfg(test)]
644mod tests {
645 use super::*;
646 use arrow_buffer::Buffer;
647 use rand::{Rng, rng};
648
649 #[test]
650 fn test_boolean_fmt_debug() {
651 let arr = BooleanArray::from(vec![true, false, false]);
652 assert_eq!(
653 "BooleanArray\n[\n true,\n false,\n false,\n]",
654 format!("{arr:?}")
655 );
656 }
657
658 #[test]
659 fn test_boolean_with_null_fmt_debug() {
660 let mut builder = BooleanArray::builder(3);
661 builder.append_value(true);
662 builder.append_null();
663 builder.append_value(false);
664 let arr = builder.finish();
665 assert_eq!(
666 "BooleanArray\n[\n true,\n null,\n false,\n]",
667 format!("{arr:?}")
668 );
669 }
670
671 #[test]
672 fn test_boolean_array_from_vec() {
673 let buf = Buffer::from([10_u8]);
674 let arr = BooleanArray::from(vec![false, true, false, true]);
675 assert_eq!(&buf, arr.values().inner());
676 assert_eq!(4, arr.len());
677 assert_eq!(0, arr.offset());
678 assert_eq!(0, arr.null_count());
679 for i in 0..4 {
680 assert!(!arr.is_null(i));
681 assert!(arr.is_valid(i));
682 assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
683 }
684 }
685
686 #[test]
687 fn test_boolean_array_from_vec_option() {
688 let buf = Buffer::from([10_u8]);
689 let arr = BooleanArray::from(vec![Some(false), Some(true), None, Some(true)]);
690 assert_eq!(&buf, arr.values().inner());
691 assert_eq!(4, arr.len());
692 assert_eq!(0, arr.offset());
693 assert_eq!(1, arr.null_count());
694 for i in 0..4 {
695 if i == 2 {
696 assert!(arr.is_null(i));
697 assert!(!arr.is_valid(i));
698 } else {
699 assert!(!arr.is_null(i));
700 assert!(arr.is_valid(i));
701 assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
702 }
703 }
704 }
705
706 #[test]
707 fn test_boolean_array_from_packed() {
708 let v = [1_u8, 2_u8, 3_u8];
709 let arr = BooleanArray::new_from_packed(v, 0, 24);
710 assert_eq!(24, arr.len());
711 assert_eq!(0, arr.offset());
712 assert_eq!(0, arr.null_count());
713 assert!(arr.nulls.is_none());
714 for i in 0..24 {
715 assert!(!arr.is_null(i));
716 assert!(arr.is_valid(i));
717 assert_eq!(
718 i == 0 || i == 9 || i == 16 || i == 17,
719 arr.value(i),
720 "failed t {i}"
721 )
722 }
723 }
724
725 #[test]
726 fn test_boolean_array_from_slice_u8() {
727 let v: Vec<u8> = vec![1, 2, 3];
728 let slice = &v[..];
729 let arr = BooleanArray::new_from_u8(slice);
730 assert_eq!(24, arr.len());
731 assert_eq!(0, arr.offset());
732 assert_eq!(0, arr.null_count());
733 assert!(arr.nulls().is_none());
734 for i in 0..24 {
735 assert!(!arr.is_null(i));
736 assert!(arr.is_valid(i));
737 assert_eq!(
738 i == 0 || i == 9 || i == 16 || i == 17,
739 arr.value(i),
740 "failed t {i}"
741 )
742 }
743 }
744
745 #[test]
746 fn test_boolean_array_from_iter() {
747 let v = vec![Some(false), Some(true), Some(false), Some(true)];
748 let arr = v.into_iter().collect::<BooleanArray>();
749 assert_eq!(4, arr.len());
750 assert_eq!(0, arr.offset());
751 assert_eq!(0, arr.null_count());
752 assert!(arr.nulls().is_none());
753 for i in 0..3 {
754 assert!(!arr.is_null(i));
755 assert!(arr.is_valid(i));
756 assert_eq!(i == 1 || i == 3, arr.value(i), "failed at {i}")
757 }
758 }
759
760 #[test]
761 fn test_boolean_array_from_non_nullable_iter() {
762 let v = vec![true, false, true];
763 let arr = v.into_iter().collect::<BooleanArray>();
764 assert_eq!(3, arr.len());
765 assert_eq!(0, arr.offset());
766 assert_eq!(0, arr.null_count());
767 assert!(arr.nulls().is_none());
768
769 assert!(arr.value(0));
770 assert!(!arr.value(1));
771 assert!(arr.value(2));
772 }
773
774 #[test]
775 fn test_boolean_array_from_nullable_iter() {
776 let v = vec![Some(true), None, Some(false), None];
777 let arr = v.into_iter().collect::<BooleanArray>();
778 assert_eq!(4, arr.len());
779 assert_eq!(0, arr.offset());
780 assert_eq!(2, arr.null_count());
781 assert!(arr.nulls().is_some());
782
783 assert!(arr.is_valid(0));
784 assert!(arr.is_null(1));
785 assert!(arr.is_valid(2));
786 assert!(arr.is_null(3));
787
788 assert!(arr.value(0));
789 assert!(!arr.value(2));
790 }
791
792 #[test]
793 fn test_boolean_array_from_nullable_trusted_len_iter() {
794 let v = vec![Some(true), None, Some(false), None];
796 let expected = v.clone().into_iter().collect::<BooleanArray>();
797 let actual = unsafe {
798 BooleanArray::from_trusted_len_iter(v.into_iter())
800 };
801 assert_eq!(expected, actual);
802 }
803
804 #[test]
805 fn test_boolean_array_from_iter_with_larger_upper_bound() {
806 let iterator = vec![Some(true), None, Some(false), None]
809 .into_iter()
810 .filter(Option::is_some);
811 let arr = iterator.collect::<BooleanArray>();
812 assert_eq!(2, arr.len());
813 }
814
815 #[test]
816 fn test_boolean_array_builder() {
817 let buf = Buffer::from([27_u8]);
820 let buf2 = buf.clone();
821 let data = ArrayData::builder(DataType::Boolean)
822 .len(5)
823 .offset(2)
824 .add_buffer(buf)
825 .build()
826 .unwrap();
827 let arr = BooleanArray::from(data);
828 assert_eq!(&buf2, arr.values().inner());
829 assert_eq!(5, arr.len());
830 assert_eq!(2, arr.offset());
831 assert_eq!(0, arr.null_count());
832 for i in 0..3 {
833 assert_eq!(i != 0, arr.value(i), "failed at {i}");
834 }
835 }
836
837 #[test]
838 #[should_panic(
839 expected = "Trying to access an element at index 4 from a BooleanArray of length 3"
840 )]
841 fn test_fixed_size_binary_array_get_value_index_out_of_bound() {
842 let v = vec![Some(true), None, Some(false)];
843 let array = v.into_iter().collect::<BooleanArray>();
844
845 array.value(4);
846 }
847
848 #[test]
849 #[should_panic(expected = "BooleanArray data should contain a single buffer only \
850 (values buffer)")]
851 #[cfg(not(feature = "force_validate"))]
854 fn test_boolean_array_invalid_buffer_len() {
855 let data = unsafe {
856 ArrayData::builder(DataType::Boolean)
857 .len(5)
858 .build_unchecked()
859 };
860 drop(BooleanArray::from(data));
861 }
862
863 #[test]
864 #[should_panic(expected = "BooleanArray expected ArrayData with type Boolean got Int32")]
865 fn test_from_array_data_validation() {
866 let _ = BooleanArray::from(ArrayData::new_empty(&DataType::Int32));
867 }
868
869 #[test]
870 #[cfg_attr(miri, ignore)] fn test_true_false_count() {
872 let mut rng = rng();
873
874 for _ in 0..10 {
875 let d: Vec<_> = (0..2000).map(|_| rng.random_bool(0.5)).collect();
877 let b = BooleanArray::from(d.clone());
878
879 let expected_true = d.iter().filter(|x| **x).count();
880 assert_eq!(b.true_count(), expected_true);
881 assert_eq!(b.false_count(), d.len() - expected_true);
882
883 let d: Vec<_> = (0..2000)
885 .map(|_| rng.random_bool(0.5).then(|| rng.random_bool(0.5)))
886 .collect();
887 let b = BooleanArray::from(d.clone());
888
889 let expected_true = d.iter().filter(|x| matches!(x, Some(true))).count();
890 assert_eq!(b.true_count(), expected_true);
891
892 let expected_false = d.iter().filter(|x| matches!(x, Some(false))).count();
893 assert_eq!(b.false_count(), expected_false);
894 }
895 }
896
897 #[test]
898 fn test_into_parts() {
899 let boolean_array = [Some(true), None, Some(false)]
900 .into_iter()
901 .collect::<BooleanArray>();
902 let (values, nulls) = boolean_array.into_parts();
903 assert_eq!(values.values(), &[0b0000_0001]);
904 assert!(nulls.is_some());
905 assert_eq!(nulls.unwrap().buffer().as_slice(), &[0b0000_0101]);
906
907 let boolean_array =
908 BooleanArray::from(vec![false, false, false, false, false, false, false, true]);
909 let (values, nulls) = boolean_array.into_parts();
910 assert_eq!(values.values(), &[0b1000_0000]);
911 assert!(nulls.is_none());
912 }
913
914 #[test]
915 fn test_new_null_array() {
916 let arr = BooleanArray::new_null(5);
917
918 assert_eq!(arr.len(), 5);
919 assert_eq!(arr.null_count(), 5);
920 assert_eq!(arr.true_count(), 0);
921 assert_eq!(arr.false_count(), 0);
922
923 for i in 0..5 {
924 assert!(arr.is_null(i));
925 assert!(!arr.is_valid(i));
926 }
927 }
928
929 #[test]
930 fn test_slice_with_nulls() {
931 let arr = BooleanArray::from(vec![Some(true), None, Some(false)]);
932 let sliced = arr.slice(1, 2);
933
934 assert_eq!(sliced.len(), 2);
935 assert_eq!(sliced.null_count(), 1);
936
937 assert!(sliced.is_null(0));
938 assert!(sliced.is_valid(1));
939 assert!(!sliced.value(1));
940 }
941
942 #[test]
943 fn test_has_true_has_false_all_true() {
944 let arr = BooleanArray::from(vec![true, true, true]);
945 assert!(arr.has_true());
946 assert!(!arr.has_false());
947 }
948
949 #[test]
950 fn test_has_true_has_false_all_false() {
951 let arr = BooleanArray::from(vec![false, false, false]);
952 assert!(!arr.has_true());
953 assert!(arr.has_false());
954 }
955
956 #[test]
957 fn test_has_true_has_false_mixed() {
958 let arr = BooleanArray::from(vec![true, false, true]);
959 assert!(arr.has_true());
960 assert!(arr.has_false());
961 }
962
963 #[test]
964 fn test_has_true_has_false_empty() {
965 let arr = BooleanArray::from(Vec::<bool>::new());
966 assert!(!arr.has_true());
967 assert!(!arr.has_false());
968 }
969
970 #[test]
971 fn test_has_true_has_false_nulls_all_valid_true() {
972 let arr = BooleanArray::from(vec![Some(true), None, Some(true)]);
973 assert!(arr.has_true());
974 assert!(!arr.has_false());
975 }
976
977 #[test]
978 fn test_has_true_has_false_nulls_all_valid_false() {
979 let arr = BooleanArray::from(vec![Some(false), None, Some(false)]);
980 assert!(!arr.has_true());
981 assert!(arr.has_false());
982 }
983
984 #[test]
985 fn test_has_true_has_false_all_null() {
986 let arr = BooleanArray::new_null(5);
987 assert!(!arr.has_true());
988 assert!(!arr.has_false());
989 }
990
991 #[test]
992 fn test_has_false_aligned_suffix_all_true() {
993 let arr = BooleanArray::from(vec![true; 129]);
994 assert!(arr.has_true());
995 assert!(!arr.has_false());
996 }
997
998 #[test]
999 fn test_has_false_non_aligned_all_true() {
1000 let arr = BooleanArray::from(vec![true; 65]);
1002 assert!(arr.has_true());
1003 assert!(!arr.has_false());
1004 }
1005
1006 #[test]
1007 fn test_has_false_non_aligned_last_false() {
1008 let mut values = vec![true; 64];
1010 values.push(false);
1011 let arr = BooleanArray::from(values);
1012 assert!(arr.has_true());
1013 assert!(arr.has_false());
1014 }
1015
1016 #[test]
1017 fn test_has_false_exact_64_all_true() {
1018 let arr = BooleanArray::from(vec![true; 64]);
1020 assert!(arr.has_true());
1021 assert!(!arr.has_false());
1022 }
1023
1024 #[test]
1025 fn test_has_true_has_false_unaligned_slices() {
1026 let cases = [
1027 (1, 129, true, false),
1028 (3, 130, true, false),
1029 (5, 65, true, false),
1030 (7, 64, true, false),
1031 ];
1032
1033 let base = BooleanArray::from(vec![true; 300]);
1034
1035 for (offset, len, expected_has_true, expected_has_false) in cases {
1036 let arr = base.slice(offset, len);
1037 assert_eq!(
1038 arr.has_true(),
1039 expected_has_true,
1040 "offset={offset} len={len}"
1041 );
1042 assert_eq!(
1043 arr.has_false(),
1044 expected_has_false,
1045 "offset={offset} len={len}"
1046 );
1047 }
1048 }
1049
1050 #[test]
1051 fn test_has_true_has_false_exact_multiples_of_64() {
1052 let cases = [
1053 (64, true, false),
1054 (128, true, false),
1055 (192, true, false),
1056 (256, true, false),
1057 ];
1058
1059 for (len, expected_has_true, expected_has_false) in cases {
1060 let arr = BooleanArray::from(vec![true; len]);
1061 assert_eq!(arr.has_true(), expected_has_true, "len={len}");
1062 assert_eq!(arr.has_false(), expected_has_false, "len={len}");
1063 }
1064 }
1065}