@@ -45,49 +45,48 @@ where
45
45
/// The first component of the value yielded by `WithPosition`.
46
46
/// Indicates the position of this element in the iterator results.
47
47
///
48
- /// When handling the first or last position,
49
- /// remember to consider the special case of [`Position::Only`].
50
- ///
51
48
/// See [`.with_position()`](crate::Itertools::with_position) for more information.
52
49
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
53
- pub enum Position {
54
- /// This is the first element, and there is more than one element.
55
- First ,
56
- /// This is neither the first nor the last element.
57
- Middle ,
58
- /// This is the last element, and there was more than one element.
59
- Last ,
60
- /// This is the only element.
61
- Only ,
50
+ pub struct Position {
51
+ /// This is the initial element (also true if there's exactly one element)
52
+ pub is_first : bool ,
53
+ /// This is the final element (also true if there's exactly one element)
54
+ pub is_last : bool ,
55
+ }
56
+
57
+ impl Position {
58
+ /// This is the first and the last element at the same time, and there are no more elements
59
+ pub fn is_exactly_one ( self ) -> bool {
60
+ self . is_first && self . is_last
61
+ }
62
+
63
+ /// This is neither first nor last element, and there will be more elements
64
+ pub fn is_middle ( self ) -> bool {
65
+ !self . is_first && !self . is_last
66
+ }
67
+
68
+ /// This is the initial element (also true if there's exactly one element)
69
+ pub fn is_first ( self ) -> bool {
70
+ self . is_first
71
+ }
72
+
73
+ /// This is the final element (also true if there's exactly one element)
74
+ pub fn is_last ( self ) -> bool {
75
+ self . is_last
76
+ }
62
77
}
63
78
64
79
impl < I : Iterator > Iterator for WithPosition < I > {
65
80
type Item = ( Position , I :: Item ) ;
66
81
67
82
fn next ( & mut self ) -> Option < Self :: Item > {
68
- match self . peekable . next ( ) {
69
- Some ( item) => {
70
- if !self . handled_first {
71
- // Haven't seen the first item yet, and there is one to give.
72
- self . handled_first = true ;
73
- // Peek to see if this is also the last item,
74
- // in which case tag it as `Only`.
75
- match self . peekable . peek ( ) {
76
- Some ( _) => Some ( ( Position :: First , item) ) ,
77
- None => Some ( ( Position :: Only , item) ) ,
78
- }
79
- } else {
80
- // Have seen the first item, and there's something left.
81
- // Peek to see if this is the last item.
82
- match self . peekable . peek ( ) {
83
- Some ( _) => Some ( ( Position :: Middle , item) ) ,
84
- None => Some ( ( Position :: Last , item) ) ,
85
- }
86
- }
87
- }
88
- // Iterator is finished.
89
- None => None ,
90
- }
83
+ let item = self . peekable . next ( ) ?;
84
+
85
+ let is_last = self . peekable . peek ( ) . is_none ( ) ;
86
+ let is_first = !self . handled_first ;
87
+ self . handled_first = true ;
88
+
89
+ Some ( ( Position { is_first, is_last } , item) )
91
90
}
92
91
93
92
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -105,18 +104,36 @@ impl<I: Iterator> Iterator for WithPosition<I> {
105
104
match self . peekable . next ( ) {
106
105
Some ( second) => {
107
106
let first = std:: mem:: replace ( & mut head, second) ;
108
- init = f ( init, ( Position :: First , first) ) ;
107
+ let position = Position {
108
+ is_first : true ,
109
+ is_last : false ,
110
+ } ;
111
+ init = f ( init, ( position, first) ) ;
112
+ }
113
+ None => {
114
+ let position = Position {
115
+ is_first : true ,
116
+ is_last : true ,
117
+ } ;
118
+ return f ( init, ( position, head) ) ;
109
119
}
110
- None => return f ( init, ( Position :: Only , head) ) ,
111
120
}
112
121
}
113
122
// Have seen the first item, and there's something left.
114
123
init = self . peekable . fold ( init, |acc, mut item| {
115
124
std:: mem:: swap ( & mut head, & mut item) ;
116
- f ( acc, ( Position :: Middle , item) )
125
+ let position = Position {
126
+ is_first : false ,
127
+ is_last : false ,
128
+ } ;
129
+ f ( acc, ( position, item) )
117
130
} ) ;
131
+ let position = Position {
132
+ is_first : false ,
133
+ is_last : true ,
134
+ } ;
118
135
// The "head" is now the last item.
119
- init = f ( init, ( Position :: Last , head) ) ;
136
+ init = f ( init, ( position , head) ) ;
120
137
}
121
138
init
122
139
}
0 commit comments