Coverage Report

Created: 2025-11-05 08:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rayon-1.11.0/src/iter/chunks.rs
Line
Count
Source
1
use super::plumbing::*;
2
use super::*;
3
4
/// `Chunks` is an iterator that groups elements of an underlying iterator.
5
///
6
/// This struct is created by the [`chunks()`] method on [`IndexedParallelIterator`]
7
///
8
/// [`chunks()`]: IndexedParallelIterator::chunks()
9
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
10
#[derive(Debug, Clone)]
11
pub struct Chunks<I> {
12
    size: usize,
13
    i: I,
14
}
15
16
impl<I> Chunks<I> {
17
    /// Creates a new `Chunks` iterator
18
0
    pub(super) fn new(i: I, size: usize) -> Self {
19
0
        Chunks { i, size }
20
0
    }
21
}
22
23
impl<I> ParallelIterator for Chunks<I>
24
where
25
    I: IndexedParallelIterator,
26
{
27
    type Item = Vec<I::Item>;
28
29
0
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
30
0
    where
31
0
        C: Consumer<Vec<I::Item>>,
32
    {
33
0
        bridge(self, consumer)
34
0
    }
35
36
0
    fn opt_len(&self) -> Option<usize> {
37
0
        Some(self.len())
38
0
    }
39
}
40
41
impl<I> IndexedParallelIterator for Chunks<I>
42
where
43
    I: IndexedParallelIterator,
44
{
45
0
    fn drive<C>(self, consumer: C) -> C::Result
46
0
    where
47
0
        C: Consumer<Self::Item>,
48
    {
49
0
        bridge(self, consumer)
50
0
    }
51
52
0
    fn len(&self) -> usize {
53
0
        self.i.len().div_ceil(self.size)
54
0
    }
55
56
0
    fn with_producer<CB>(self, callback: CB) -> CB::Output
57
0
    where
58
0
        CB: ProducerCallback<Self::Item>,
59
    {
60
0
        let len = self.i.len();
61
0
        return self.i.with_producer(Callback {
62
0
            size: self.size,
63
0
            len,
64
0
            callback,
65
0
        });
66
67
        struct Callback<CB> {
68
            size: usize,
69
            len: usize,
70
            callback: CB,
71
        }
72
73
        impl<T, CB> ProducerCallback<T> for Callback<CB>
74
        where
75
            CB: ProducerCallback<Vec<T>>,
76
        {
77
            type Output = CB::Output;
78
79
0
            fn callback<P>(self, base: P) -> CB::Output
80
0
            where
81
0
                P: Producer<Item = T>,
82
            {
83
0
                let producer = ChunkProducer::new(self.size, self.len, base, Vec::from_iter);
84
0
                self.callback.callback(producer)
85
0
            }
86
        }
87
0
    }
88
}
89
90
pub(super) struct ChunkProducer<P, F> {
91
    chunk_size: usize,
92
    len: usize,
93
    base: P,
94
    map: F,
95
}
96
97
impl<P, F> ChunkProducer<P, F> {
98
0
    pub(super) fn new(chunk_size: usize, len: usize, base: P, map: F) -> Self {
99
0
        Self {
100
0
            chunk_size,
101
0
            len,
102
0
            base,
103
0
            map,
104
0
        }
105
0
    }
106
}
107
108
impl<P, F, T> Producer for ChunkProducer<P, F>
109
where
110
    P: Producer,
111
    F: Fn(P::IntoIter) -> T + Send + Clone,
112
{
113
    type Item = T;
114
    type IntoIter = std::iter::Map<ChunkSeq<P>, F>;
115
116
0
    fn into_iter(self) -> Self::IntoIter {
117
0
        let chunks = ChunkSeq {
118
0
            chunk_size: self.chunk_size,
119
0
            len: self.len,
120
0
            inner: if self.len > 0 { Some(self.base) } else { None },
121
        };
122
0
        chunks.map(self.map)
123
0
    }
124
125
0
    fn split_at(self, index: usize) -> (Self, Self) {
126
0
        let elem_index = Ord::min(index * self.chunk_size, self.len);
127
0
        let (left, right) = self.base.split_at(elem_index);
128
0
        (
129
0
            ChunkProducer {
130
0
                chunk_size: self.chunk_size,
131
0
                len: elem_index,
132
0
                base: left,
133
0
                map: self.map.clone(),
134
0
            },
135
0
            ChunkProducer {
136
0
                chunk_size: self.chunk_size,
137
0
                len: self.len - elem_index,
138
0
                base: right,
139
0
                map: self.map,
140
0
            },
141
0
        )
142
0
    }
143
144
0
    fn min_len(&self) -> usize {
145
0
        self.base.min_len().div_ceil(self.chunk_size)
146
0
    }
147
148
0
    fn max_len(&self) -> usize {
149
0
        self.base.max_len() / self.chunk_size
150
0
    }
151
}
152
153
pub(super) struct ChunkSeq<P> {
154
    chunk_size: usize,
155
    len: usize,
156
    inner: Option<P>,
157
}
158
159
impl<P> Iterator for ChunkSeq<P>
160
where
161
    P: Producer,
162
{
163
    type Item = P::IntoIter;
164
165
0
    fn next(&mut self) -> Option<Self::Item> {
166
0
        let producer = self.inner.take()?;
167
0
        if self.len > self.chunk_size {
168
0
            let (left, right) = producer.split_at(self.chunk_size);
169
0
            self.inner = Some(right);
170
0
            self.len -= self.chunk_size;
171
0
            Some(left.into_iter())
172
        } else {
173
0
            debug_assert!(self.len > 0);
174
0
            self.len = 0;
175
0
            Some(producer.into_iter())
176
        }
177
0
    }
178
179
0
    fn size_hint(&self) -> (usize, Option<usize>) {
180
0
        let len = self.len();
181
0
        (len, Some(len))
182
0
    }
183
}
184
185
impl<P> ExactSizeIterator for ChunkSeq<P>
186
where
187
    P: Producer,
188
{
189
    #[inline]
190
0
    fn len(&self) -> usize {
191
0
        self.len.div_ceil(self.chunk_size)
192
0
    }
193
}
194
195
impl<P> DoubleEndedIterator for ChunkSeq<P>
196
where
197
    P: Producer,
198
{
199
0
    fn next_back(&mut self) -> Option<Self::Item> {
200
0
        let producer = self.inner.take()?;
201
0
        if self.len > self.chunk_size {
202
0
            let mut size = self.len % self.chunk_size;
203
0
            if size == 0 {
204
0
                size = self.chunk_size;
205
0
            }
206
0
            let (left, right) = producer.split_at(self.len - size);
207
0
            self.inner = Some(left);
208
0
            self.len -= size;
209
0
            Some(right.into_iter())
210
        } else {
211
0
            debug_assert!(self.len > 0);
212
0
            self.len = 0;
213
0
            Some(producer.into_iter())
214
        }
215
0
    }
216
}