itertools/
with_position.rs1use std::iter::{Fuse,Peekable, FusedIterator};
2
3#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
9pub struct WithPosition<I>
10 where I: Iterator,
11{
12 handled_first: bool,
13 peekable: Peekable<Fuse<I>>,
14}
15
16impl<I> Clone for WithPosition<I>
17 where I: Clone + Iterator,
18 I::Item: Clone,
19{
20 clone_fields!(handled_first, peekable);
21}
22
23pub fn with_position<I>(iter: I) -> WithPosition<I>
25 where I: Iterator,
26{
27 WithPosition {
28 handled_first: false,
29 peekable: iter.fuse().peekable(),
30 }
31}
32
33#[derive(Copy, Clone, Debug, PartialEq)]
38pub enum Position<T> {
39 First(T),
41 Middle(T),
43 Last(T),
45 Only(T),
47}
48
49impl<T> Position<T> {
50 pub fn into_inner(self) -> T {
52 match self {
53 Position::First(x) |
54 Position::Middle(x) |
55 Position::Last(x) |
56 Position::Only(x) => x,
57 }
58 }
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
95impl<I> ExactSizeIterator for WithPosition<I>
96 where I: ExactSizeIterator,
97{ }
98
99impl<I: Iterator> FusedIterator for WithPosition<I>
100{}