-
Notifications
You must be signed in to change notification settings - Fork 346
Expand file tree
/
Copy pathpeeking_map_while.rs
More file actions
86 lines (77 loc) · 2.09 KB
/
peeking_map_while.rs
File metadata and controls
86 lines (77 loc) · 2.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use core::{iter::Peekable, mem};
use either::Either;
use crate::PutBack;
/// An iterator adaptor that takes items while a closure returns [`Either::Left`].
///
/// See [`.peeking_map_while()`](crate::Itertools::peeking_map_while)
/// for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct PeekingMapWhile<'a, I, F> {
pub(crate) iter: &'a mut I,
pub(crate) accept: F,
}
impl<I, F, O> Iterator for PeekingMapWhile<'_, I, F>
where
I: PeekingMapNext,
F: FnMut(I::Item) -> Either<O, I::Item>,
{
type Item = O;
fn next(&mut self) -> Option<O> {
self.iter.peeking_map_next(&mut self.accept)
}
}
/// A trait used in [`PeekingMapWhile`]
pub trait PeekingMapNext: Iterator {
/// If it returns [`Either::Right`] then it should be reinserted to the iterator otherwise it should be returned
fn peeking_map_next<O>(
&mut self,
accept: impl FnMut(Self::Item) -> Either<O, Self::Item>,
) -> Option<O>;
}
impl<I> PeekingMapNext for Peekable<I>
where
I: Iterator,
I::Item: Default,
{
fn peeking_map_next<O>(
&mut self,
mut accept: impl FnMut(I::Item) -> Either<O, I::Item>,
) -> Option<O> {
let dest = self.peek_mut()?;
let item = mem::take(dest);
let out = accept(item);
match out {
Either::Left(out) => {
self.next();
Some(out)
}
Either::Right(item) => {
*dest = item;
None
}
}
}
}
impl<I> PeekingMapNext for PutBack<I>
where
I: Iterator,
{
fn peeking_map_next<O>(
&mut self,
mut accept: impl FnMut(I::Item) -> Either<O, I::Item>,
) -> Option<O> {
match accept(self.next()?) {
Either::Left(out) => Some(out),
Either::Right(item) => {
self.put_back(item);
None
}
}
}
}
impl<'a, I, F> std::fmt::Debug for PeekingMapWhile<'a, I, F>
where
I: Iterator + std::fmt::Debug + 'a,
{
debug_fmt_fields!(PeekingTakeWhile, iter);
}