]> git.proxmox.com Git - rustc.git/blob - vendor/itertools-0.7.8/src/with_position.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / vendor / itertools-0.7.8 / src / with_position.rs
1 use std::iter::{Fuse,Peekable};
2
3 /// An iterator adaptor that wraps each element in an [`Position`](../enum.Position.html).
4 ///
5 /// Iterator element type is `Position<I::Item>`.
6 ///
7 /// See [`.with_position()`](../trait.Itertools.html#method.with_position) for more information.
8 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
9 pub struct WithPosition<I>
10 where I: Iterator,
11 {
12 handled_first: bool,
13 peekable: Peekable<Fuse<I>>,
14 }
15
16 /// Create a new `WithPosition` iterator.
17 pub fn with_position<I>(iter: I) -> WithPosition<I>
18 where I: Iterator,
19 {
20 WithPosition {
21 handled_first: false,
22 peekable: iter.fuse().peekable(),
23 }
24 }
25
26 /// A value yielded by `WithPosition`.
27 /// Indicates the position of this element in the iterator results.
28 ///
29 /// See [`.with_position()`](trait.Itertools.html#method.with_position) for more information.
30 #[derive(Copy, Clone, Debug, PartialEq)]
31 pub enum Position<T> {
32 /// This is the first element.
33 First(T),
34 /// This is neither the first nor the last element.
35 Middle(T),
36 /// This is the last element.
37 Last(T),
38 /// This is the only element.
39 Only(T),
40 }
41
42 impl<T> Position<T> {
43 /// Return the inner value.
44 pub fn into_inner(self) -> T {
45 match self {
46 Position::First(x) |
47 Position::Middle(x) |
48 Position::Last(x) |
49 Position::Only(x) => x,
50 }
51 }
52 }
53
54 impl<I: Iterator> Iterator for WithPosition<I> {
55 type Item = Position<I::Item>;
56
57 fn next(&mut self) -> Option<Self::Item> {
58 match self.peekable.next() {
59 Some(item) => {
60 if !self.handled_first {
61 // Haven't seen the first item yet, and there is one to give.
62 self.handled_first = true;
63 // Peek to see if this is also the last item,
64 // in which case tag it as `Only`.
65 match self.peekable.peek() {
66 Some(_) => Some(Position::First(item)),
67 None => Some(Position::Only(item)),
68 }
69 } else {
70 // Have seen the first item, and there's something left.
71 // Peek to see if this is the last item.
72 match self.peekable.peek() {
73 Some(_) => Some(Position::Middle(item)),
74 None => Some(Position::Last(item)),
75 }
76 }
77 }
78 // Iterator is finished.
79 None => None,
80 }
81 }
82
83 fn size_hint(&self) -> (usize, Option<usize>) {
84 self.peekable.size_hint()
85 }
86 }
87
88 impl<I> ExactSizeIterator for WithPosition<I>
89 where I: ExactSizeIterator,
90 { }