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 {
39 First,
41 Middle,
43 Last,
45 Only,
47}
48
49impl<I: Iterator> Iterator for WithPosition<I> {
50 type Item = (Position, I::Item);
51
52 fn next(&mut self) -> Option<Self::Item> {
53 match self.peekable.next() {
54 Some(item) => {
55 if !self.handled_first {
56 self.handled_first = true;
58 match self.peekable.peek() {
61 Some(_) => Some((Position::First, item)),
62 None => Some((Position::Only, item)),
63 }
64 } else {
65 match self.peekable.peek() {
68 Some(_) => Some((Position::Middle, item)),
69 None => Some((Position::Last, item)),
70 }
71 }
72 }
73 None => None,
75 }
76 }
77
78 fn size_hint(&self) -> (usize, Option<usize>) {
79 self.peekable.size_hint()
80 }
81}
82
83impl<I> ExactSizeIterator for WithPosition<I>
84 where I: ExactSizeIterator,
85{ }
86
87impl<I: Iterator> FusedIterator for WithPosition<I>
88{}