1use arrow::array::*;
2
3use crate::prelude::*;
4
5pub mod par;
6
7impl<T> ChunkedArray<T>
8where
9 T: PolarsDataType,
10{
11 #[inline]
12 pub fn iter(&self) -> impl PolarsIterator<Item = Option<T::Physical<'_>>> {
13 unsafe {
15 self.downcast_iter()
16 .flat_map(|arr| arr.iter())
17 .trust_my_length(self.len())
18 }
19 }
20}
21
22pub trait PolarsIterator:
25 ExactSizeIterator + DoubleEndedIterator + Send + Sync + TrustedLen
26{
27}
28unsafe impl<I> TrustedLen for Box<dyn PolarsIterator<Item = I> + '_> {}
29
30impl<T: ?Sized> PolarsIterator for T where
32 T: ExactSizeIterator + DoubleEndedIterator + Send + Sync + TrustedLen
33{
34}
35
36impl<'a, T> IntoIterator for &'a ChunkedArray<T>
37where
38 T: PolarsNumericType,
39{
40 type Item = Option<T::Native>;
41 type IntoIter = Box<dyn PolarsIterator<Item = Self::Item> + 'a>;
42 fn into_iter(self) -> Self::IntoIter {
43 Box::new(
44 unsafe {
46 self.downcast_iter()
47 .flatten()
48 .map(|x| x.copied())
49 .trust_my_length(self.len())
50 },
51 )
52 }
53}
54
55impl<'a> IntoIterator for &'a BooleanChunked {
56 type Item = Option<bool>;
57 type IntoIter = Box<dyn PolarsIterator<Item = Self::Item> + 'a>;
58 fn into_iter(self) -> Self::IntoIter {
59 unsafe { Box::new(self.downcast_iter().flatten().trust_my_length(self.len())) }
61 }
62}
63
64pub struct BoolIterNoNull<'a> {
66 array: &'a BooleanArray,
67 current: usize,
68 current_end: usize,
69}
70
71impl<'a> BoolIterNoNull<'a> {
72 pub fn new(array: &'a BooleanArray) -> Self {
74 BoolIterNoNull {
75 array,
76 current: 0,
77 current_end: array.len(),
78 }
79 }
80}
81
82impl Iterator for BoolIterNoNull<'_> {
83 type Item = bool;
84
85 fn next(&mut self) -> Option<Self::Item> {
86 if self.current == self.current_end {
87 None
88 } else {
89 let old = self.current;
90 self.current += 1;
91 unsafe { Some(self.array.value_unchecked(old)) }
92 }
93 }
94
95 fn size_hint(&self) -> (usize, Option<usize>) {
96 (
97 self.array.len() - self.current,
98 Some(self.array.len() - self.current),
99 )
100 }
101}
102
103impl DoubleEndedIterator for BoolIterNoNull<'_> {
104 fn next_back(&mut self) -> Option<Self::Item> {
105 if self.current_end == self.current {
106 None
107 } else {
108 self.current_end -= 1;
109 unsafe { Some(self.array.value_unchecked(self.current_end)) }
110 }
111 }
112}
113
114impl ExactSizeIterator for BoolIterNoNull<'_> {}
116
117impl BooleanChunked {
118 #[allow(clippy::wrong_self_convention)]
119 #[doc(hidden)]
120 pub fn into_no_null_iter(
121 &self,
122 ) -> impl '_ + Send + Sync + ExactSizeIterator<Item = bool> + DoubleEndedIterator + TrustedLen
123 {
124 unsafe {
126 self.downcast_iter()
127 .flat_map(BoolIterNoNull::new)
128 .trust_my_length(self.len())
129 }
130 }
131}
132
133impl<'a> IntoIterator for &'a StringChunked {
134 type Item = Option<&'a str>;
135 type IntoIter = Box<dyn PolarsIterator<Item = Self::Item> + 'a>;
136 fn into_iter(self) -> Self::IntoIter {
137 unsafe { Box::new(self.downcast_iter().flatten().trust_my_length(self.len())) }
139 }
140}
141
142impl StringChunked {
143 #[allow(clippy::wrong_self_convention)]
144 #[doc(hidden)]
145 pub fn into_no_null_iter(
146 &self,
147 ) -> impl '_ + Send + Sync + ExactSizeIterator<Item = &str> + DoubleEndedIterator + TrustedLen
148 {
149 unsafe {
151 self.downcast_iter()
152 .flat_map(|arr| arr.values_iter())
153 .trust_my_length(self.len())
154 }
155 }
156}
157
158impl<'a> IntoIterator for &'a BinaryChunked {
159 type Item = Option<&'a [u8]>;
160 type IntoIter = Box<dyn PolarsIterator<Item = Self::Item> + 'a>;
161 fn into_iter(self) -> Self::IntoIter {
162 unsafe { Box::new(self.downcast_iter().flatten().trust_my_length(self.len())) }
164 }
165}
166
167impl BinaryChunked {
168 #[allow(clippy::wrong_self_convention)]
169 #[doc(hidden)]
170 pub fn into_no_null_iter(
171 &self,
172 ) -> impl '_ + Send + Sync + ExactSizeIterator<Item = &[u8]> + DoubleEndedIterator + TrustedLen
173 {
174 unsafe {
176 self.downcast_iter()
177 .flat_map(|arr| arr.values_iter())
178 .trust_my_length(self.len())
179 }
180 }
181}
182
183impl<'a> IntoIterator for &'a BinaryOffsetChunked {
184 type Item = Option<&'a [u8]>;
185 type IntoIter = Box<dyn PolarsIterator<Item = Self::Item> + 'a>;
186 fn into_iter(self) -> Self::IntoIter {
187 unsafe { Box::new(self.downcast_iter().flatten().trust_my_length(self.len())) }
189 }
190}
191
192impl BinaryOffsetChunked {
193 #[allow(clippy::wrong_self_convention)]
194 #[doc(hidden)]
195 pub fn into_no_null_iter(
196 &self,
197 ) -> impl '_ + Send + Sync + ExactSizeIterator<Item = &[u8]> + DoubleEndedIterator + TrustedLen
198 {
199 unsafe {
201 self.downcast_iter()
202 .flat_map(|arr| arr.values_iter())
203 .trust_my_length(self.len())
204 }
205 }
206}
207
208impl<'a> IntoIterator for &'a ListChunked {
209 type Item = Option<Series>;
210 type IntoIter = Box<dyn PolarsIterator<Item = Self::Item> + 'a>;
211 fn into_iter(self) -> Self::IntoIter {
212 let dtype = self.inner_dtype();
213
214 if self.null_count() == 0 {
215 unsafe {
217 Box::new(
218 self.downcast_iter()
219 .flat_map(|arr| arr.iter().unwrap_required())
220 .trust_my_length(self.len())
221 .map(move |arr| {
222 Some(Series::from_chunks_and_dtype_unchecked(
223 PlSmallStr::EMPTY,
224 vec![arr],
225 dtype,
226 ))
227 }),
228 )
229 }
230 } else {
231 unsafe {
233 Box::new(
234 self.downcast_iter()
235 .flat_map(|arr| arr.iter())
236 .trust_my_length(self.len())
237 .map(move |arr| {
238 arr.map(|arr| {
239 Series::from_chunks_and_dtype_unchecked(
240 PlSmallStr::EMPTY,
241 vec![arr],
242 dtype,
243 )
244 })
245 }),
246 )
247 }
248 }
249 }
250}
251
252impl ListChunked {
253 #[allow(clippy::wrong_self_convention)]
254 #[doc(hidden)]
255 pub fn into_no_null_iter(
256 &self,
257 ) -> impl '_ + Send + Sync + ExactSizeIterator<Item = Series> + DoubleEndedIterator + TrustedLen
258 {
259 let inner_type = self.inner_dtype();
260 unsafe {
261 self.downcast_iter()
262 .flat_map(|arr| arr.values_iter())
263 .map(move |arr| {
264 Series::from_chunks_and_dtype_unchecked(
265 PlSmallStr::EMPTY,
266 vec![arr],
267 inner_type,
268 )
269 })
270 .trust_my_length(self.len())
271 }
272 }
273}
274
275#[cfg(feature = "dtype-array")]
276impl<'a> IntoIterator for &'a ArrayChunked {
277 type Item = Option<Series>;
278 type IntoIter = Box<dyn PolarsIterator<Item = Self::Item> + 'a>;
279 fn into_iter(self) -> Self::IntoIter {
280 let dtype = self.inner_dtype();
281
282 if self.null_count() == 0 {
283 unsafe {
285 Box::new(
286 self.downcast_iter()
287 .flat_map(|arr| arr.iter().unwrap_required())
288 .trust_my_length(self.len())
289 .map(move |arr| {
290 Some(Series::from_chunks_and_dtype_unchecked(
291 PlSmallStr::EMPTY,
292 vec![arr],
293 dtype,
294 ))
295 }),
296 )
297 }
298 } else {
299 unsafe {
301 Box::new(
302 self.downcast_iter()
303 .flat_map(|arr| arr.iter())
304 .trust_my_length(self.len())
305 .map(move |arr| {
306 arr.map(|arr| {
307 Series::from_chunks_and_dtype_unchecked(
308 PlSmallStr::EMPTY,
309 vec![arr],
310 dtype,
311 )
312 })
313 }),
314 )
315 }
316 }
317 }
318}
319
320#[cfg(feature = "dtype-array")]
321pub struct FixedSizeListIterNoNull<'a> {
322 array: &'a FixedSizeListArray,
323 inner_type: DataType,
324 current: usize,
325 current_end: usize,
326}
327
328#[cfg(feature = "dtype-array")]
329impl<'a> FixedSizeListIterNoNull<'a> {
330 pub fn new(array: &'a FixedSizeListArray, inner_type: DataType) -> Self {
332 FixedSizeListIterNoNull {
333 array,
334 inner_type,
335 current: 0,
336 current_end: array.len(),
337 }
338 }
339}
340
341#[cfg(feature = "dtype-array")]
342impl Iterator for FixedSizeListIterNoNull<'_> {
343 type Item = Series;
344
345 fn next(&mut self) -> Option<Self::Item> {
346 if self.current == self.current_end {
347 None
348 } else {
349 let old = self.current;
350 self.current += 1;
351 unsafe {
352 Some(Series::from_chunks_and_dtype_unchecked(
353 PlSmallStr::EMPTY,
354 vec![self.array.value_unchecked(old)],
355 &self.inner_type,
356 ))
357 }
358 }
359 }
360
361 fn size_hint(&self) -> (usize, Option<usize>) {
362 (
363 self.array.len() - self.current,
364 Some(self.array.len() - self.current),
365 )
366 }
367}
368
369#[cfg(feature = "dtype-array")]
370impl DoubleEndedIterator for FixedSizeListIterNoNull<'_> {
371 fn next_back(&mut self) -> Option<Self::Item> {
372 if self.current_end == self.current {
373 None
374 } else {
375 self.current_end -= 1;
376 unsafe {
377 Some(
378 Series::try_from((
379 PlSmallStr::EMPTY,
380 self.array.value_unchecked(self.current_end),
381 ))
382 .unwrap(),
383 )
384 }
385 }
386 }
387}
388
389#[cfg(feature = "dtype-array")]
391impl ExactSizeIterator for FixedSizeListIterNoNull<'_> {}
392
393#[cfg(feature = "dtype-array")]
394impl ArrayChunked {
395 #[allow(clippy::wrong_self_convention)]
396 #[doc(hidden)]
397 pub fn into_no_null_iter(
398 &self,
399 ) -> impl '_ + Send + Sync + ExactSizeIterator<Item = Series> + DoubleEndedIterator + TrustedLen
400 {
401 let inner_type = self.inner_dtype();
403 unsafe {
404 self.downcast_iter()
405 .flat_map(move |arr| FixedSizeListIterNoNull::new(arr, inner_type.clone()))
406 .trust_my_length(self.len())
407 }
408 }
409}
410
411#[cfg(feature = "object")]
412impl<'a, T> IntoIterator for &'a ObjectChunked<T>
413where
414 T: PolarsObject,
415{
416 type Item = Option<&'a T>;
417 type IntoIter = Box<dyn PolarsIterator<Item = Self::Item> + 'a>;
418 fn into_iter(self) -> Self::IntoIter {
419 unsafe { Box::new(self.downcast_iter().flatten().trust_my_length(self.len())) }
421 }
422}
423
424#[cfg(feature = "object")]
425impl<T: PolarsObject> ObjectChunked<T> {
426 #[allow(clippy::wrong_self_convention)]
427 #[doc(hidden)]
428 pub fn into_no_null_iter(
429 &self,
430 ) -> impl '_ + Send + Sync + ExactSizeIterator<Item = &T> + DoubleEndedIterator + TrustedLen
431 {
432 unsafe {
434 self.downcast_iter()
435 .flat_map(|arr| arr.values_iter())
436 .trust_my_length(self.len())
437 }
438 }
439}
440
441pub struct SomeIterator<I>(I)
444where
445 I: Iterator;
446
447impl<I> Iterator for SomeIterator<I>
448where
449 I: Iterator,
450{
451 type Item = Option<I::Item>;
452
453 fn next(&mut self) -> Option<Self::Item> {
454 self.0.next().map(Some)
455 }
456
457 fn size_hint(&self) -> (usize, Option<usize>) {
458 self.0.size_hint()
459 }
460}
461
462impl<I> DoubleEndedIterator for SomeIterator<I>
463where
464 I: DoubleEndedIterator,
465{
466 fn next_back(&mut self) -> Option<Self::Item> {
467 self.0.next_back().map(Some)
468 }
469}
470
471impl<I> ExactSizeIterator for SomeIterator<I> where I: ExactSizeIterator {}
472
473#[cfg(test)]
474mod test {
475 use crate::prelude::*;
476
477 #[test]
478 fn out_of_bounds() {
479 let mut a = UInt32Chunked::from_slice(PlSmallStr::from_static("a"), &[1, 2, 3]);
480 let b = UInt32Chunked::from_slice(PlSmallStr::from_static("a"), &[1, 2, 3]);
481 a.append(&b).unwrap();
482
483 let v = a.into_iter().collect::<Vec<_>>();
484 assert_eq!(
485 vec![Some(1u32), Some(2), Some(3), Some(1), Some(2), Some(3)],
486 v
487 )
488 }
489
490 macro_rules! impl_test_iter_single_chunk {
502 ($test_name:ident, $ca_type:ty, $first_val:expr, $second_val:expr, $third_val:expr) => {
503 #[test]
504 fn $test_name() {
505 let a = <$ca_type>::from_slice(
506 PlSmallStr::from_static("test"),
507 &[$first_val, $second_val, $third_val],
508 );
509
510 let mut it = a.into_iter();
512 assert_eq!(it.next(), Some(Some($first_val)));
513 assert_eq!(it.next(), Some(Some($second_val)));
514 assert_eq!(it.next(), Some(Some($third_val)));
515 assert_eq!(it.next(), None);
516 assert_eq!(it.next_back(), None);
518
519 let mut it = a.into_iter();
521 assert_eq!(it.next_back(), Some(Some($third_val)));
522 assert_eq!(it.next_back(), Some(Some($second_val)));
523 assert_eq!(it.next_back(), Some(Some($first_val)));
524 assert_eq!(it.next_back(), None);
525 assert_eq!(it.next(), None);
527
528 let mut it = a.into_iter();
530 assert_eq!(it.next_back(), Some(Some($third_val)));
531 assert_eq!(it.next(), Some(Some($first_val)));
532 assert_eq!(it.next(), Some(Some($second_val)));
533 assert_eq!(it.next(), None);
535 assert_eq!(it.next_back(), None);
537
538 let mut it = a.into_iter();
540 assert_eq!(it.next(), Some(Some($first_val)));
541 assert_eq!(it.next_back(), Some(Some($third_val)));
542 assert_eq!(it.next_back(), Some(Some($second_val)));
543 assert_eq!(it.next_back(), None);
544 assert_eq!(it.next(), None);
546 }
547 };
548 }
549
550 impl_test_iter_single_chunk!(num_iter_single_chunk, UInt32Chunked, 1, 2, 3);
551 impl_test_iter_single_chunk!(utf8_iter_single_chunk, StringChunked, "a", "b", "c");
552 impl_test_iter_single_chunk!(bool_iter_single_chunk, BooleanChunked, true, true, false);
553
554 macro_rules! impl_test_iter_single_chunk_null_check {
566 ($test_name:ident, $ca_type:ty, $first_val:expr, $second_val:expr, $third_val:expr) => {
567 #[test]
568 fn $test_name() {
569 let a = <$ca_type>::new(
570 PlSmallStr::from_static("test"),
571 &[$first_val, $second_val, $third_val],
572 );
573
574 let mut it = a.into_iter();
576 assert_eq!(it.next(), Some($first_val));
577 assert_eq!(it.next(), Some($second_val));
578 assert_eq!(it.next(), Some($third_val));
579 assert_eq!(it.next(), None);
580 assert_eq!(it.next_back(), None);
582
583 let mut it = a.into_iter();
585 assert_eq!(it.next_back(), Some($third_val));
586 assert_eq!(it.next_back(), Some($second_val));
587 assert_eq!(it.next_back(), Some($first_val));
588 assert_eq!(it.next_back(), None);
589 assert_eq!(it.next(), None);
591
592 let mut it = a.into_iter();
594 assert_eq!(it.next_back(), Some($third_val));
595 assert_eq!(it.next(), Some($first_val));
596 assert_eq!(it.next(), Some($second_val));
597 assert_eq!(it.next(), None);
599 assert_eq!(it.next_back(), None);
601
602 let mut it = a.into_iter();
604 assert_eq!(it.next(), Some($first_val));
605 assert_eq!(it.next_back(), Some($third_val));
606 assert_eq!(it.next_back(), Some($second_val));
607 assert_eq!(it.next_back(), None);
608 assert_eq!(it.next(), None);
610 }
611 };
612 }
613
614 impl_test_iter_single_chunk_null_check!(
615 num_iter_single_chunk_null_check,
616 UInt32Chunked,
617 Some(1),
618 None,
619 Some(3)
620 );
621 impl_test_iter_single_chunk_null_check!(
622 utf8_iter_single_chunk_null_check,
623 StringChunked,
624 Some("a"),
625 None,
626 Some("c")
627 );
628 impl_test_iter_single_chunk_null_check!(
629 bool_iter_single_chunk_null_check,
630 BooleanChunked,
631 Some(true),
632 None,
633 Some(false)
634 );
635
636 macro_rules! impl_test_iter_many_chunk {
648 ($test_name:ident, $ca_type:ty, $first_val:expr, $second_val:expr, $third_val:expr) => {
649 #[test]
650 fn $test_name() {
651 let mut a = <$ca_type>::from_slice(
652 PlSmallStr::from_static("test"),
653 &[$first_val, $second_val],
654 );
655 let a_b = <$ca_type>::from_slice(PlSmallStr::EMPTY, &[$third_val]);
656 a.append(&a_b).unwrap();
657
658 let mut it = a.into_iter();
660 assert_eq!(it.next(), Some(Some($first_val)));
661 assert_eq!(it.next(), Some(Some($second_val)));
662 assert_eq!(it.next(), Some(Some($third_val)));
663 assert_eq!(it.next(), None);
664 assert_eq!(it.next_back(), None);
666
667 let mut it = a.into_iter();
669 assert_eq!(it.next_back(), Some(Some($third_val)));
670 assert_eq!(it.next_back(), Some(Some($second_val)));
671 assert_eq!(it.next_back(), Some(Some($first_val)));
672 assert_eq!(it.next_back(), None);
673 assert_eq!(it.next(), None);
675
676 let mut it = a.into_iter();
678 assert_eq!(it.next_back(), Some(Some($third_val)));
679 assert_eq!(it.next(), Some(Some($first_val)));
680 assert_eq!(it.next(), Some(Some($second_val)));
681 assert_eq!(it.next(), None);
683 assert_eq!(it.next_back(), None);
685
686 let mut it = a.into_iter();
688 assert_eq!(it.next(), Some(Some($first_val)));
689 assert_eq!(it.next_back(), Some(Some($third_val)));
690 assert_eq!(it.next_back(), Some(Some($second_val)));
691 assert_eq!(it.next_back(), None);
692 assert_eq!(it.next(), None);
694 }
695 };
696 }
697
698 impl_test_iter_many_chunk!(num_iter_many_chunk, UInt32Chunked, 1, 2, 3);
699 impl_test_iter_many_chunk!(utf8_iter_many_chunk, StringChunked, "a", "b", "c");
700 impl_test_iter_many_chunk!(bool_iter_many_chunk, BooleanChunked, true, true, false);
701
702 macro_rules! impl_test_iter_many_chunk_null_check {
714 ($test_name:ident, $ca_type:ty, $first_val:expr, $second_val:expr, $third_val:expr) => {
715 #[test]
716 fn $test_name() {
717 let mut a =
718 <$ca_type>::new(PlSmallStr::from_static("test"), &[$first_val, $second_val]);
719 let a_b = <$ca_type>::new(PlSmallStr::EMPTY, &[$third_val]);
720 a.append(&a_b).unwrap();
721
722 let mut it = a.into_iter();
724 assert_eq!(it.next(), Some($first_val));
725 assert_eq!(it.next(), Some($second_val));
726 assert_eq!(it.next(), Some($third_val));
727 assert_eq!(it.next(), None);
728 assert_eq!(it.next_back(), None);
730
731 let mut it = a.into_iter();
733 assert_eq!(it.next_back(), Some($third_val));
734 assert_eq!(it.next_back(), Some($second_val));
735 assert_eq!(it.next_back(), Some($first_val));
736 assert_eq!(it.next_back(), None);
737 assert_eq!(it.next(), None);
739
740 let mut it = a.into_iter();
742 assert_eq!(it.next_back(), Some($third_val));
743 assert_eq!(it.next(), Some($first_val));
744 assert_eq!(it.next(), Some($second_val));
745 assert_eq!(it.next(), None);
747 assert_eq!(it.next_back(), None);
749
750 let mut it = a.into_iter();
752 assert_eq!(it.next(), Some($first_val));
753 assert_eq!(it.next_back(), Some($third_val));
754 assert_eq!(it.next_back(), Some($second_val));
755 assert_eq!(it.next_back(), None);
756 assert_eq!(it.next(), None);
758 }
759 };
760 }
761
762 impl_test_iter_many_chunk_null_check!(
763 num_iter_many_chunk_null_check,
764 UInt32Chunked,
765 Some(1),
766 None,
767 Some(3)
768 );
769 impl_test_iter_many_chunk_null_check!(
770 utf8_iter_many_chunk_null_check,
771 StringChunked,
772 Some("a"),
773 None,
774 Some("c")
775 );
776 impl_test_iter_many_chunk_null_check!(
777 bool_iter_many_chunk_null_check,
778 BooleanChunked,
779 Some(true),
780 None,
781 Some(false)
782 );
783
784 macro_rules! impl_test_no_null_iter_single_chunk {
796 ($test_name:ident, $ca_type:ty, $first_val:expr, $second_val:expr, $third_val:expr) => {
797 #[test]
798 fn $test_name() {
799 let a = <$ca_type>::from_slice(
800 PlSmallStr::from_static("test"),
801 &[$first_val, $second_val, $third_val],
802 );
803
804 let mut it = a.into_no_null_iter();
806 assert_eq!(it.next(), Some($first_val));
807 assert_eq!(it.next(), Some($second_val));
808 assert_eq!(it.next(), Some($third_val));
809 assert_eq!(it.next(), None);
810 assert_eq!(it.next_back(), None);
812
813 let mut it = a.into_no_null_iter();
815 assert_eq!(it.next_back(), Some($third_val));
816 assert_eq!(it.next_back(), Some($second_val));
817 assert_eq!(it.next_back(), Some($first_val));
818 assert_eq!(it.next_back(), None);
819 assert_eq!(it.next(), None);
821
822 let mut it = a.into_no_null_iter();
824 assert_eq!(it.next_back(), Some($third_val));
825 assert_eq!(it.next(), Some($first_val));
826 assert_eq!(it.next(), Some($second_val));
827 assert_eq!(it.next(), None);
829 assert_eq!(it.next_back(), None);
831
832 let mut it = a.into_no_null_iter();
834 assert_eq!(it.next(), Some($first_val));
835 assert_eq!(it.next_back(), Some($third_val));
836 assert_eq!(it.next_back(), Some($second_val));
837 assert_eq!(it.next_back(), None);
838 assert_eq!(it.next(), None);
840 }
841 };
842 }
843
844 impl_test_no_null_iter_single_chunk!(num_no_null_iter_single_chunk, UInt32Chunked, 1, 2, 3);
845 impl_test_no_null_iter_single_chunk!(
846 utf8_no_null_iter_single_chunk,
847 StringChunked,
848 "a",
849 "b",
850 "c"
851 );
852 impl_test_no_null_iter_single_chunk!(
853 bool_no_null_iter_single_chunk,
854 BooleanChunked,
855 true,
856 true,
857 false
858 );
859
860 macro_rules! impl_test_no_null_iter_many_chunk {
872 ($test_name:ident, $ca_type:ty, $first_val:expr, $second_val:expr, $third_val:expr) => {
873 #[test]
874 fn $test_name() {
875 let mut a = <$ca_type>::from_slice(
876 PlSmallStr::from_static("test"),
877 &[$first_val, $second_val],
878 );
879 let a_b = <$ca_type>::from_slice(PlSmallStr::EMPTY, &[$third_val]);
880 a.append(&a_b).unwrap();
881
882 let mut it = a.into_no_null_iter();
884 assert_eq!(it.next(), Some($first_val));
885 assert_eq!(it.next(), Some($second_val));
886 assert_eq!(it.next(), Some($third_val));
887 assert_eq!(it.next(), None);
888 assert_eq!(it.next_back(), None);
890
891 let mut it = a.into_no_null_iter();
893 assert_eq!(it.next_back(), Some($third_val));
894 assert_eq!(it.next_back(), Some($second_val));
895 assert_eq!(it.next_back(), Some($first_val));
896 assert_eq!(it.next_back(), None);
897 assert_eq!(it.next(), None);
899
900 let mut it = a.into_no_null_iter();
902 assert_eq!(it.next_back(), Some($third_val));
903 assert_eq!(it.next(), Some($first_val));
904 assert_eq!(it.next(), Some($second_val));
905 assert_eq!(it.next(), None);
907 assert_eq!(it.next_back(), None);
909
910 let mut it = a.into_no_null_iter();
912 assert_eq!(it.next(), Some($first_val));
913 assert_eq!(it.next_back(), Some($third_val));
914 assert_eq!(it.next_back(), Some($second_val));
915 assert_eq!(it.next_back(), None);
916 assert_eq!(it.next(), None);
918 }
919 };
920 }
921
922 impl_test_no_null_iter_many_chunk!(num_no_null_iter_many_chunk, UInt32Chunked, 1, 2, 3);
923 impl_test_no_null_iter_many_chunk!(utf8_no_null_iter_many_chunk, StringChunked, "a", "b", "c");
924 impl_test_no_null_iter_many_chunk!(
925 bool_no_null_iter_many_chunk,
926 BooleanChunked,
927 true,
928 true,
929 false
930 );
931
932 const SKIP_ITERATOR_SIZE: usize = 10;
934
935 macro_rules! impl_test_iter_skip {
946 ($test_name:ident, $skip_values:expr, $first_val:expr, $second_val:expr, $ca_init_block:block) => {
947 #[test]
948 fn $test_name() {
949 let a = $ca_init_block;
950
951 let mut it = a.into_iter();
953 assert_eq!(it.next(), Some($first_val));
954
955 let mut it = it.skip($skip_values);
957 assert_eq!(it.next(), Some($second_val));
958
959 let mut it = it.skip(SKIP_ITERATOR_SIZE);
961 assert_eq!(it.next(), None);
962 }
963 };
964 }
965
966 fn generate_utf8_vec(size: usize) -> Vec<String> {
968 (0..size).map(|n| n.to_string()).collect()
969 }
970
971 fn generate_opt_utf8_vec(size: usize) -> Vec<Option<String>> {
973 (0..size)
974 .map(|n| {
975 if n % 2 == 0 {
976 Some(n.to_string())
977 } else {
978 None
979 }
980 })
981 .collect()
982 }
983
984 impl_test_iter_skip!(utf8_iter_single_chunk_skip, 8, Some("0"), Some("9"), {
985 StringChunked::from_slice(
986 PlSmallStr::from_static("test"),
987 &generate_utf8_vec(SKIP_ITERATOR_SIZE),
988 )
989 });
990
991 impl_test_iter_skip!(
992 utf8_iter_single_chunk_null_check_skip,
993 8,
994 Some("0"),
995 None,
996 {
997 StringChunked::new(
998 PlSmallStr::from_static("test"),
999 &generate_opt_utf8_vec(SKIP_ITERATOR_SIZE),
1000 )
1001 }
1002 );
1003
1004 impl_test_iter_skip!(utf8_iter_many_chunk_skip, 18, Some("0"), Some("9"), {
1005 let mut a = StringChunked::from_slice(
1006 PlSmallStr::from_static("test"),
1007 &generate_utf8_vec(SKIP_ITERATOR_SIZE),
1008 );
1009 let a_b = StringChunked::from_slice(
1010 PlSmallStr::from_static("test"),
1011 &generate_utf8_vec(SKIP_ITERATOR_SIZE),
1012 );
1013 a.append(&a_b).unwrap();
1014 a
1015 });
1016
1017 impl_test_iter_skip!(utf8_iter_many_chunk_null_check_skip, 18, Some("0"), None, {
1018 let mut a = StringChunked::new(
1019 PlSmallStr::from_static("test"),
1020 &generate_opt_utf8_vec(SKIP_ITERATOR_SIZE),
1021 );
1022 let a_b = StringChunked::new(
1023 PlSmallStr::from_static("test"),
1024 &generate_opt_utf8_vec(SKIP_ITERATOR_SIZE),
1025 );
1026 a.append(&a_b).unwrap();
1027 a
1028 });
1029
1030 fn generate_boolean_vec(size: usize) -> Vec<bool> {
1032 (0..size).map(|n| n % 2 == 0).collect()
1033 }
1034
1035 fn generate_opt_boolean_vec(size: usize) -> Vec<Option<bool>> {
1040 (0..size)
1041 .map(|n| if n % 3 == 0 { None } else { Some(n % 2 == 0) })
1042 .collect()
1043 }
1044
1045 impl_test_iter_skip!(bool_iter_single_chunk_skip, 8, Some(true), Some(false), {
1046 BooleanChunked::from_slice(
1047 PlSmallStr::from_static("test"),
1048 &generate_boolean_vec(SKIP_ITERATOR_SIZE),
1049 )
1050 });
1051
1052 impl_test_iter_skip!(bool_iter_single_chunk_null_check_skip, 8, None, None, {
1053 BooleanChunked::new(
1054 PlSmallStr::from_static("test"),
1055 &generate_opt_boolean_vec(SKIP_ITERATOR_SIZE),
1056 )
1057 });
1058
1059 impl_test_iter_skip!(bool_iter_many_chunk_skip, 18, Some(true), Some(false), {
1060 let mut a = BooleanChunked::from_slice(
1061 PlSmallStr::from_static("test"),
1062 &generate_boolean_vec(SKIP_ITERATOR_SIZE),
1063 );
1064 let a_b = BooleanChunked::from_slice(
1065 PlSmallStr::from_static("test"),
1066 &generate_boolean_vec(SKIP_ITERATOR_SIZE),
1067 );
1068 a.append(&a_b).unwrap();
1069 a
1070 });
1071
1072 impl_test_iter_skip!(bool_iter_many_chunk_null_check_skip, 18, None, None, {
1073 let mut a = BooleanChunked::new(
1074 PlSmallStr::from_static("test"),
1075 &generate_opt_boolean_vec(SKIP_ITERATOR_SIZE),
1076 );
1077 let a_b = BooleanChunked::new(
1078 PlSmallStr::from_static("test"),
1079 &generate_opt_boolean_vec(SKIP_ITERATOR_SIZE),
1080 );
1081 a.append(&a_b).unwrap();
1082 a
1083 });
1084}