Skip to main content

orx_concurrent_iter/chain/
con_iter_known_len_i.rs

1use crate::{
2    ConcurrentIter, ExactSizeConcurrentIter,
3    chain::chunk_puller_known_len_i::ChainedChunkPullerKnownLenI,
4};
5
6/// Chain of two concurrent iterators where the length of the first iterator is
7/// known with certainly; i.e., `I` implements `ExactSizeConcurrentIter`.
8pub struct ChainKnownLenI<I, J>
9where
10    I: ConcurrentIter,
11    J: ConcurrentIter<Item = I::Item>,
12{
13    i: I,
14    j: J,
15    len_i: usize,
16}
17
18impl<I, J> ChainKnownLenI<I, J>
19where
20    I: ConcurrentIter,
21    J: ConcurrentIter<Item = I::Item>,
22{
23    pub(crate) fn new(i: I, j: J, len_i: usize) -> Self {
24        Self { i, j, len_i }
25    }
26}
27
28impl<I, J> ConcurrentIter for ChainKnownLenI<I, J>
29where
30    I: ConcurrentIter,
31    J: ConcurrentIter<Item = I::Item>,
32{
33    type Item = I::Item;
34
35    type SequentialIter = core::iter::Chain<I::SequentialIter, J::SequentialIter>;
36
37    type ChunkPuller<'i>
38        = ChainedChunkPullerKnownLenI<'i, I, J>
39    where
40        Self: 'i;
41
42    fn is_source_serialized() -> bool {
43        I::is_source_serialized() || J::is_source_serialized()
44    }
45
46    fn into_seq_iter(self) -> Self::SequentialIter {
47        self.i.into_seq_iter().chain(self.j.into_seq_iter())
48    }
49
50    fn skip_to_end(&self) {
51        self.i.skip_to_end();
52        self.j.skip_to_end();
53    }
54
55    fn next(&self) -> Option<Self::Item> {
56        self.i.next().or_else(|| self.j.next())
57    }
58
59    fn next_with_idx(&self) -> Option<(usize, Self::Item)> {
60        self.i
61            .next_with_idx()
62            .or_else(|| self.j.next_with_idx().map(|(idx, x)| (self.len_i + idx, x)))
63    }
64
65    fn size_hint(&self) -> (usize, Option<usize>) {
66        let (l1, u1) = self.i.size_hint();
67        let (l2, u2) = self.j.size_hint();
68        match (u1, u2) {
69            (Some(u1), Some(u2)) => (l1 + l2, Some(u1 + u2)),
70            _ => (l1 + l2, None),
71        }
72    }
73
74    fn is_completed_when_none_returned(&self) -> bool {
75        true
76    }
77
78    fn chunk_puller(&self, chunk_size: usize) -> Self::ChunkPuller<'_> {
79        ChainedChunkPullerKnownLenI::new(&self.i, &self.j, chunk_size, self.len_i)
80    }
81}
82
83impl<I, J> ExactSizeConcurrentIter for ChainKnownLenI<I, J>
84where
85    I: ExactSizeConcurrentIter,
86    J: ExactSizeConcurrentIter<Item = I::Item>,
87{
88    fn len(&self) -> usize {
89        self.i.len() + self.j.len()
90    }
91}