itertools/
with_position.rs1use std::fmt;
2use std::iter::{Fuse, FusedIterator, Peekable};
3
4#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
10pub struct WithPosition<I>
11where
12 I: Iterator,
13{
14 handled_first: bool,
15 peekable: Peekable<Fuse<I>>,
16}
17
18impl<I> fmt::Debug for WithPosition<I>
19where
20 I: Iterator,
21 Peekable<Fuse<I>>: fmt::Debug,
22{
23 debug_fmt_fields!(WithPosition, handled_first, peekable);
24}
25
26impl<I> Clone for WithPosition<I>
27where
28 I: Clone + Iterator,
29 I::Item: Clone,
30{
31 clone_fields!(handled_first, peekable);
32}
33
34pub fn with_position<I>(iter: I) -> WithPosition<I>
36where
37 I: Iterator,
38{
39 WithPosition {
40 handled_first: false,
41 peekable: iter.fuse().peekable(),
42 }
43}
44
45#[derive(Copy, Clone, Debug, PartialEq, Eq)]
50pub enum Position {
51 First,
53 Middle,
55 Last,
57 Only,
59}
60
61impl<I: Iterator> Iterator for WithPosition<I> {
62 type Item = (Position, I::Item);
63
64 fn next(&mut self) -> Option<Self::Item> {
65 match self.peekable.next() {
66 Some(item) => {
67 if !self.handled_first {
68 self.handled_first = true;
70 match self.peekable.peek() {
73 Some(_) => Some((Position::First, item)),
74 None => Some((Position::Only, item)),
75 }
76 } else {
77 match self.peekable.peek() {
80 Some(_) => Some((Position::Middle, item)),
81 None => Some((Position::Last, item)),
82 }
83 }
84 }
85 None => None,
87 }
88 }
89
90 fn size_hint(&self) -> (usize, Option<usize>) {
91 self.peekable.size_hint()
92 }
93
94 fn fold<B, F>(mut self, mut init: B, mut f: F) -> B
95 where
96 F: FnMut(B, Self::Item) -> B,
97 {
98 if let Some(mut head) = self.peekable.next() {
99 if !self.handled_first {
100 match self.peekable.next() {
103 Some(second) => {
104 let first = std::mem::replace(&mut head, second);
105 init = f(init, (Position::First, first));
106 }
107 None => return f(init, (Position::Only, head)),
108 }
109 }
110 init = self.peekable.fold(init, |acc, mut item| {
112 std::mem::swap(&mut head, &mut item);
113 f(acc, (Position::Middle, item))
114 });
115 init = f(init, (Position::Last, head));
117 }
118 init
119 }
120}
121
122impl<I> ExactSizeIterator for WithPosition<I> where I: ExactSizeIterator {}
123
124impl<I: Iterator> FusedIterator for WithPosition<I> {}