]> git.proxmox.com Git - rustc.git/blame - src/vendor/itertools-0.6.5/src/with_position.rs
New upstream version 1.25.0+dfsg1
[rustc.git] / src / vendor / itertools-0.6.5 / src / with_position.rs
CommitLineData
2c00a5a8
XL
1use 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.
8pub 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.
16pub 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)]
30pub 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
41impl<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
53impl<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
87impl<I> ExactSizeIterator for WithPosition<I>
88 where I: ExactSizeIterator,
89{ }