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