1 use super::plumbing
::*;
4 use std
::iter
::{self, Fuse}
;
6 /// `Intersperse` is an iterator that inserts a particular item between each
7 /// item of the adapted iterator. This struct is created by the
8 /// [`intersperse()`] method on [`ParallelIterator`]
10 /// [`intersperse()`]: trait.ParallelIterator.html#method.intersperse
11 /// [`ParallelIterator`]: trait.ParallelIterator.html
12 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
13 #[derive(Clone, Debug)]
14 pub struct Intersperse
<I
>
23 impl<I
> Intersperse
<I
>
28 /// Creates a new `Intersperse` iterator
29 pub(super) fn new(base
: I
, item
: I
::Item
) -> Self {
30 Intersperse { base, item }
34 impl<I
> ParallelIterator
for Intersperse
<I
>
37 I
::Item
: Clone
+ Send
,
41 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
43 C
: UnindexedConsumer
<I
::Item
>,
45 let consumer1
= IntersperseConsumer
::new(consumer
, self.item
);
46 self.base
.drive_unindexed(consumer1
)
49 fn opt_len(&self) -> Option
<usize> {
50 match self.base
.opt_len()?
{
52 len
=> len
.checked_add(len
- 1),
57 impl<I
> IndexedParallelIterator
for Intersperse
<I
>
59 I
: IndexedParallelIterator
,
60 I
::Item
: Clone
+ Send
,
62 fn drive
<C
>(self, consumer
: C
) -> C
::Result
64 C
: Consumer
<Self::Item
>,
66 let consumer1
= IntersperseConsumer
::new(consumer
, self.item
);
67 self.base
.drive(consumer1
)
70 fn len(&self) -> usize {
71 let len
= self.base
.len();
73 len
.checked_add(len
- 1).expect("overflow")
79 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
81 CB
: ProducerCallback
<Self::Item
>,
84 return self.base
.with_producer(Callback
{
90 struct Callback
<CB
, T
> {
96 impl<T
, CB
> ProducerCallback
<T
> for Callback
<CB
, T
>
98 CB
: ProducerCallback
<T
>,
101 type Output
= CB
::Output
;
103 fn callback
<P
>(self, base
: P
) -> CB
::Output
105 P
: Producer
<Item
= T
>,
107 let producer
= IntersperseProducer
::new(base
, self.item
, self.len
);
108 self.callback
.callback(producer
)
114 struct IntersperseProducer
<P
>
124 impl<P
> IntersperseProducer
<P
>
128 fn new(base
: P
, item
: P
::Item
, len
: usize) -> Self {
129 IntersperseProducer
{
138 impl<P
> Producer
for IntersperseProducer
<P
>
141 P
::Item
: Clone
+ Send
,
144 type IntoIter
= IntersperseIter
<P
::IntoIter
>;
146 fn into_iter(self) -> Self::IntoIter
{
148 base
: self.base
.into_iter().fuse(),
150 clone_first
: self.len
> 0 && self.clone_first
,
152 // If there's more than one item, then even lengths end the opposite
153 // of how they started with respect to interspersed clones.
154 clone_last
: self.len
> 1 && ((self.len
& 1 == 0) ^
self.clone_first
),
158 fn min_len(&self) -> usize {
161 fn max_len(&self) -> usize {
165 fn split_at(self, index
: usize) -> (Self, Self) {
166 debug_assert
!(index
<= self.len
);
168 // The left needs half of the items from the base producer, and the
169 // other half will be our interspersed item. If we're not leading with
170 // a cloned item, then we need to round up the base number of items,
171 // otherwise round down.
172 let base_index
= (index
+ !self.clone_first
as usize) / 2;
173 let (left_base
, right_base
) = self.base
.split_at(base_index
);
175 let left
= IntersperseProducer
{
177 item
: self.item
.clone(),
179 clone_first
: self.clone_first
,
182 let right
= IntersperseProducer
{
185 len
: self.len
- index
,
187 // If the index is odd, the right side toggles `clone_first`.
188 clone_first
: (index
& 1 == 1) ^
self.clone_first
,
194 fn fold_with
<F
>(self, folder
: F
) -> F
196 F
: Folder
<Self::Item
>,
198 let folder1
= IntersperseFolder
{
201 clone_first
: self.clone_first
,
203 self.base
.fold_with(folder1
).base
207 struct IntersperseIter
<I
>
217 impl<I
> Iterator
for IntersperseIter
<I
>
219 I
: DoubleEndedIterator
+ ExactSizeIterator
,
224 fn next(&mut self) -> Option
<Self::Item
> {
225 if self.clone_first
{
226 self.clone_first
= false;
227 Some(self.item
.clone())
228 } else if let next @
Some(_
) = self.base
.next() {
229 // If there are any items left, we'll need another clone in front.
230 self.clone_first
= self.base
.len() != 0;
232 } else if self.clone_last
{
233 self.clone_last
= false;
234 Some(self.item
.clone())
240 fn size_hint(&self) -> (usize, Option
<usize>) {
241 let len
= self.len();
246 impl<I
> DoubleEndedIterator
for IntersperseIter
<I
>
248 I
: DoubleEndedIterator
+ ExactSizeIterator
,
251 fn next_back(&mut self) -> Option
<Self::Item
> {
253 self.clone_last
= false;
254 Some(self.item
.clone())
255 } else if let next_back @
Some(_
) = self.base
.next_back() {
256 // If there are any items left, we'll need another clone in back.
257 self.clone_last
= self.base
.len() != 0;
259 } else if self.clone_first
{
260 self.clone_first
= false;
261 Some(self.item
.clone())
268 impl<I
> ExactSizeIterator
for IntersperseIter
<I
>
270 I
: DoubleEndedIterator
+ ExactSizeIterator
,
273 fn len(&self) -> usize {
274 let len
= self.base
.len();
275 len
+ len
.saturating_sub(1) + self.clone_first
as usize + self.clone_last
as usize
279 struct IntersperseConsumer
<C
, T
> {
282 clone_first
: Cell
<bool
>,
285 impl<C
, T
> IntersperseConsumer
<C
, T
>
289 fn new(base
: C
, item
: T
) -> Self {
290 IntersperseConsumer
{
293 clone_first
: false.into(),
298 impl<C
, T
> Consumer
<T
> for IntersperseConsumer
<C
, T
>
303 type Folder
= IntersperseFolder
<C
::Folder
, T
>;
304 type Reducer
= C
::Reducer
;
305 type Result
= C
::Result
;
307 fn split_at(mut self, index
: usize) -> (Self, Self, Self::Reducer
) {
308 // We'll feed twice as many items to the base consumer, except if we're
309 // not currently leading with a cloned item, then it's one less.
310 let base_index
= index
+ index
.saturating_sub(!self.clone_first
.get() as usize);
311 let (left
, right
, reducer
) = self.base
.split_at(base_index
);
313 let right
= IntersperseConsumer
{
315 item
: self.item
.clone(),
316 clone_first
: true.into(),
319 (self, right
, reducer
)
322 fn into_folder(self) -> Self::Folder
{
324 base
: self.base
.into_folder(),
326 clone_first
: self.clone_first
.get(),
330 fn full(&self) -> bool
{
335 impl<C
, T
> UnindexedConsumer
<T
> for IntersperseConsumer
<C
, T
>
337 C
: UnindexedConsumer
<T
>,
340 fn split_off_left(&self) -> Self {
341 let left
= IntersperseConsumer
{
342 base
: self.base
.split_off_left(),
343 item
: self.item
.clone(),
344 clone_first
: self.clone_first
.clone(),
346 self.clone_first
.set(true);
350 fn to_reducer(&self) -> Self::Reducer
{
351 self.base
.to_reducer()
355 struct IntersperseFolder
<C
, T
> {
361 impl<C
, T
> Folder
<T
> for IntersperseFolder
<C
, T
>
366 type Result
= C
::Result
;
368 fn consume(mut self, item
: T
) -> Self {
369 if self.clone_first
{
370 self.base
= self.base
.consume(self.item
.clone());
371 if self.base
.full() {
375 self.clone_first
= true;
377 self.base
= self.base
.consume(item
);
381 fn consume_iter
<I
>(self, iter
: I
) -> Self
383 I
: IntoIterator
<Item
= T
>,
385 let mut clone_first
= self.clone_first
;
386 let between_item
= self.item
;
387 let base
= self.base
.consume_iter(iter
.into_iter().flat_map(|item
| {
388 let first
= if clone_first
{
389 Some(between_item
.clone())
394 first
.into_iter().chain(iter
::once(item
))
403 fn complete(self) -> C
::Result
{
407 fn full(&self) -> bool
{