orx_concurrent_iter/chain/
con_iter_unknown_len_i.rs1use crate::{
2 ConcurrentIter, ExactSizeConcurrentIter,
3 chain::chunk_puller_unknown_len_i::ChainedChunkPullerUnknownLenI,
4};
5use core::sync::atomic::{AtomicUsize, Ordering};
6
7pub struct ChainUnknownLenI<I, J>
10where
11 I: ConcurrentIter,
12 J: ConcurrentIter<Item = I::Item>,
13{
14 pub(super) i: I,
15 pub(super) j: J,
16 pub(super) num_pulled_i: AtomicUsize,
17}
18
19impl<I, J> ChainUnknownLenI<I, J>
20where
21 I: ConcurrentIter,
22 J: ConcurrentIter<Item = I::Item>,
23{
24 pub(crate) fn new(i: I, j: J) -> Self {
25 Self {
26 i,
27 j,
28 num_pulled_i: 0.into(),
29 }
30 }
31
32 #[inline(always)]
33 pub(super) fn num_pulled_i(&self) -> usize {
34 self.num_pulled_i.load(Ordering::SeqCst)
35 }
36}
37
38impl<I, J> ConcurrentIter for ChainUnknownLenI<I, J>
39where
40 I: ConcurrentIter,
41 J: ConcurrentIter<Item = I::Item>,
42{
43 type Item = I::Item;
44
45 type SequentialIter = core::iter::Chain<I::SequentialIter, J::SequentialIter>;
46
47 type ChunkPuller<'i>
48 = ChainedChunkPullerUnknownLenI<'i, I, J>
49 where
50 Self: 'i;
51
52 fn is_source_serialized() -> bool {
53 I::is_source_serialized() || J::is_source_serialized()
54 }
55
56 fn into_seq_iter(self) -> Self::SequentialIter {
57 self.i.into_seq_iter().chain(self.j.into_seq_iter())
58 }
59
60 fn skip_to_end(&self) {
61 self.i.skip_to_end();
62 self.j.skip_to_end();
63 }
64
65 fn next(&self) -> Option<Self::Item> {
66 match self.i.next() {
67 Some(x) => {
68 _ = self.num_pulled_i.fetch_add(1, Ordering::SeqCst);
69 Some(x)
70 }
71 None => self.j.next(),
72 }
73 }
74
75 fn next_with_idx(&self) -> Option<(usize, Self::Item)> {
76 match self.i.next_with_idx() {
77 Some((idx, x)) => {
78 _ = self.num_pulled_i.fetch_add(1, Ordering::SeqCst);
79 Some((idx, x))
80 }
81 None => self
82 .j
83 .next_with_idx()
84 .map(|(idx, x)| (self.num_pulled_i() + idx, x)),
85 }
86 }
87
88 fn size_hint(&self) -> (usize, Option<usize>) {
89 let (l1, u1) = self.i.size_hint();
90 let (l2, u2) = self.j.size_hint();
91 match (u1, u2) {
92 (Some(u1), Some(u2)) => (l1 + l2, Some(u1 + u2)),
93 _ => (l1 + l2, None),
94 }
95 }
96
97 fn is_completed_when_none_returned(&self) -> bool {
98 true
99 }
100
101 fn chunk_puller(&self, chunk_size: usize) -> Self::ChunkPuller<'_> {
102 ChainedChunkPullerUnknownLenI::new(self, chunk_size)
103 }
104}
105
106impl<I, J> ExactSizeConcurrentIter for ChainUnknownLenI<I, J>
107where
108 I: ExactSizeConcurrentIter,
109 J: ExactSizeConcurrentIter<Item = I::Item>,
110{
111 fn len(&self) -> usize {
112 self.i.len() + self.j.len()
113 }
114}