1
+ use crate :: iter:: { DoubleEndedIterator , FusedIterator , Iterator , TrustedLen } ;
1
2
use crate :: ops:: Try ;
2
3
use crate :: usize;
3
4
4
- use super :: super :: { DoubleEndedIterator , FusedIterator , Iterator , TrustedLen } ;
5
-
6
5
/// An iterator that links two iterators together, in a chain.
7
6
///
8
7
/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its
@@ -14,37 +13,34 @@ use super::super::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
14
13
#[ must_use = "iterators are lazy and do nothing unless consumed" ]
15
14
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
16
15
pub struct Chain < A , B > {
17
- a : A ,
18
- b : B ,
19
- state : ChainState ,
16
+ // These are "fused" with `Option` so we don't need separate state to track which part is
17
+ // already exhausted, and we may also get niche layout for `None`. We don't use the real `Fuse`
18
+ // adapter because its specialization for `FusedIterator` unconditionally descends into the
19
+ // iterator, and that could be expensive to keep revisiting stuff like nested chains. It also
20
+ // hurts compiler performance to add more iterator layers to `Chain`.
21
+ a : Option < A > ,
22
+ b : Option < B > ,
20
23
}
21
24
impl < A , B > Chain < A , B > {
22
25
pub ( in super :: super ) fn new ( a : A , b : B ) -> Chain < A , B > {
23
- Chain { a, b , state : ChainState :: Both }
26
+ Chain { a : Some ( a ) , b : Some ( b ) }
24
27
}
25
28
}
26
29
27
- // The iterator protocol specifies that iteration ends with the return value
28
- // `None` from `.next()` (or `.next_back()`) and it is unspecified what
29
- // further calls return. The chain adaptor must account for this since it uses
30
- // two subiterators.
31
- //
32
- // It uses three states:
33
- //
34
- // - Both: `a` and `b` are remaining
35
- // - Front: `a` remaining
36
- // - Back: `b` remaining
37
- //
38
- // The fourth state (neither iterator is remaining) only occurs after Chain has
39
- // returned None once, so we don't need to store this state.
40
- #[ derive( Clone , Debug ) ]
41
- enum ChainState {
42
- // both front and back iterator are remaining
43
- Both ,
44
- // only front is remaining
45
- Front ,
46
- // only back is remaining
47
- Back ,
30
+ /// Fuse the iterator if the expression is `None`.
31
+ macro_rules! fuse {
32
+ ( $self: ident . $iter: ident . $( $call: tt) +) => {
33
+ match $self. $iter {
34
+ Some ( ref mut iter) => match iter. $( $call) + {
35
+ None => {
36
+ $self. $iter = None ;
37
+ None
38
+ }
39
+ item => item,
40
+ } ,
41
+ None => None ,
42
+ }
43
+ } ;
48
44
}
49
45
50
46
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -57,128 +53,101 @@ where
57
53
58
54
#[ inline]
59
55
fn next ( & mut self ) -> Option < A :: Item > {
60
- match self . state {
61
- ChainState :: Both => match self . a . next ( ) {
62
- elt @ Some ( ..) => elt,
63
- None => {
64
- self . state = ChainState :: Back ;
65
- self . b . next ( )
66
- }
67
- } ,
68
- ChainState :: Front => self . a . next ( ) ,
69
- ChainState :: Back => self . b . next ( ) ,
56
+ match fuse ! ( self . a. next( ) ) {
57
+ None => fuse ! ( self . b. next( ) ) ,
58
+ item => item,
70
59
}
71
60
}
72
61
73
62
#[ inline]
74
63
#[ rustc_inherit_overflow_checks]
75
64
fn count ( self ) -> usize {
76
- match self . state {
77
- ChainState :: Both => self . a . count ( ) + self . b . count ( ) ,
78
- ChainState :: Front => self . a . count ( ) ,
79
- ChainState :: Back => self . b . count ( ) ,
80
- }
65
+ let a_count = match self . a {
66
+ Some ( a) => a. count ( ) ,
67
+ None => 0 ,
68
+ } ;
69
+ let b_count = match self . b {
70
+ Some ( b) => b. count ( ) ,
71
+ None => 0 ,
72
+ } ;
73
+ a_count + b_count
81
74
}
82
75
83
- fn try_fold < Acc , F , R > ( & mut self , init : Acc , mut f : F ) -> R
76
+ fn try_fold < Acc , F , R > ( & mut self , mut acc : Acc , mut f : F ) -> R
84
77
where
85
78
Self : Sized ,
86
79
F : FnMut ( Acc , Self :: Item ) -> R ,
87
80
R : Try < Ok = Acc > ,
88
81
{
89
- let mut accum = init;
90
- match self . state {
91
- ChainState :: Both | ChainState :: Front => {
92
- accum = self . a . try_fold ( accum, & mut f) ?;
93
- if let ChainState :: Both = self . state {
94
- self . state = ChainState :: Back ;
95
- }
96
- }
97
- _ => { }
82
+ if let Some ( ref mut a) = self . a {
83
+ acc = a. try_fold ( acc, & mut f) ?;
84
+ self . a = None ;
98
85
}
99
- if let ChainState :: Back = self . state {
100
- accum = self . b . try_fold ( accum, & mut f) ?;
86
+ if let Some ( ref mut b) = self . b {
87
+ acc = b. try_fold ( acc, f) ?;
88
+ self . b = None ;
101
89
}
102
- Try :: from_ok ( accum )
90
+ Try :: from_ok ( acc )
103
91
}
104
92
105
- fn fold < Acc , F > ( self , init : Acc , mut f : F ) -> Acc
93
+ fn fold < Acc , F > ( self , mut acc : Acc , mut f : F ) -> Acc
106
94
where
107
95
F : FnMut ( Acc , Self :: Item ) -> Acc ,
108
96
{
109
- let mut accum = init;
110
- match self . state {
111
- ChainState :: Both | ChainState :: Front => {
112
- accum = self . a . fold ( accum, & mut f) ;
113
- }
114
- _ => { }
97
+ if let Some ( a) = self . a {
98
+ acc = a. fold ( acc, & mut f) ;
115
99
}
116
- match self . state {
117
- ChainState :: Both | ChainState :: Back => {
118
- accum = self . b . fold ( accum, & mut f) ;
119
- }
120
- _ => { }
100
+ if let Some ( b) = self . b {
101
+ acc = b. fold ( acc, f) ;
121
102
}
122
- accum
103
+ acc
123
104
}
124
105
125
106
#[ inline]
126
107
fn nth ( & mut self , mut n : usize ) -> Option < A :: Item > {
127
- match self . state {
128
- ChainState :: Both | ChainState :: Front => {
129
- for x in self . a . by_ref ( ) {
130
- if n == 0 {
131
- return Some ( x) ;
132
- }
133
- n -= 1 ;
134
- }
135
- if let ChainState :: Both = self . state {
136
- self . state = ChainState :: Back ;
108
+ if let Some ( ref mut a) = self . a {
109
+ while let Some ( x) = a. next ( ) {
110
+ if n == 0 {
111
+ return Some ( x) ;
137
112
}
113
+ n -= 1 ;
138
114
}
139
- ChainState :: Back => { }
115
+ self . a = None ;
140
116
}
141
- if let ChainState :: Back = self . state { self . b . nth ( n) } else { None }
117
+ fuse ! ( self . b. nth( n) )
142
118
}
143
119
144
120
#[ inline]
145
121
fn find < P > ( & mut self , mut predicate : P ) -> Option < Self :: Item >
146
122
where
147
123
P : FnMut ( & Self :: Item ) -> bool ,
148
124
{
149
- match self . state {
150
- ChainState :: Both => match self . a . find ( & mut predicate) {
151
- None => {
152
- self . state = ChainState :: Back ;
153
- self . b . find ( predicate)
154
- }
155
- v => v,
156
- } ,
157
- ChainState :: Front => self . a . find ( predicate) ,
158
- ChainState :: Back => self . b . find ( predicate) ,
125
+ match fuse ! ( self . a. find( & mut predicate) ) {
126
+ None => fuse ! ( self . b. find( predicate) ) ,
127
+ item => item,
159
128
}
160
129
}
161
130
162
131
#[ inline]
163
132
fn last ( self ) -> Option < A :: Item > {
164
- match self . state {
165
- ChainState :: Both => {
166
- // Must exhaust a before b.
167
- let a_last = self . a . last ( ) ;
168
- let b_last = self . b . last ( ) ;
169
- b_last . or ( a_last )
170
- }
171
- ChainState :: Front => self . a . last ( ) ,
172
- ChainState :: Back => self . b . last ( ) ,
173
- }
133
+ // Must exhaust a before b.
134
+ let a_last = match self . a {
135
+ Some ( a ) => a . last ( ) ,
136
+ None => None ,
137
+ } ;
138
+ let b_last = match self . b {
139
+ Some ( b ) => b . last ( ) ,
140
+ None => None ,
141
+ } ;
142
+ b_last . or ( a_last )
174
143
}
175
144
176
145
#[ inline]
177
146
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
178
- match self . state {
179
- ChainState :: Both => {
180
- let ( a_lower, a_upper) = self . a . size_hint ( ) ;
181
- let ( b_lower, b_upper) = self . b . size_hint ( ) ;
147
+ match self {
148
+ Chain { a : Some ( a ) , b : Some ( b ) } => {
149
+ let ( a_lower, a_upper) = a. size_hint ( ) ;
150
+ let ( b_lower, b_upper) = b. size_hint ( ) ;
182
151
183
152
let lower = a_lower. saturating_add ( b_lower) ;
184
153
@@ -189,8 +158,9 @@ where
189
158
190
159
( lower, upper)
191
160
}
192
- ChainState :: Front => self . a . size_hint ( ) ,
193
- ChainState :: Back => self . b . size_hint ( ) ,
161
+ Chain { a : Some ( a) , b : None } => a. size_hint ( ) ,
162
+ Chain { a : None , b : Some ( b) } => b. size_hint ( ) ,
163
+ Chain { a : None , b : None } => ( 0 , Some ( 0 ) ) ,
194
164
}
195
165
}
196
166
}
@@ -203,82 +173,71 @@ where
203
173
{
204
174
#[ inline]
205
175
fn next_back ( & mut self ) -> Option < A :: Item > {
206
- match self . state {
207
- ChainState :: Both => match self . b . next_back ( ) {
208
- elt @ Some ( ..) => elt,
209
- None => {
210
- self . state = ChainState :: Front ;
211
- self . a . next_back ( )
212
- }
213
- } ,
214
- ChainState :: Front => self . a . next_back ( ) ,
215
- ChainState :: Back => self . b . next_back ( ) ,
176
+ match fuse ! ( self . b. next_back( ) ) {
177
+ None => fuse ! ( self . a. next_back( ) ) ,
178
+ item => item,
216
179
}
217
180
}
218
181
219
182
#[ inline]
220
183
fn nth_back ( & mut self , mut n : usize ) -> Option < A :: Item > {
221
- match self . state {
222
- ChainState :: Both | ChainState :: Back => {
223
- for x in self . b . by_ref ( ) . rev ( ) {
224
- if n == 0 {
225
- return Some ( x) ;
226
- }
227
- n -= 1 ;
228
- }
229
- if let ChainState :: Both = self . state {
230
- self . state = ChainState :: Front ;
184
+ if let Some ( ref mut b) = self . b {
185
+ while let Some ( x) = b. next_back ( ) {
186
+ if n == 0 {
187
+ return Some ( x) ;
231
188
}
189
+ n -= 1 ;
232
190
}
233
- ChainState :: Front => { }
191
+ self . b = None ;
234
192
}
235
- if let ChainState :: Front = self . state { self . a . nth_back ( n) } else { None }
193
+ fuse ! ( self . a. nth_back( n) )
236
194
}
237
195
238
- fn try_rfold < Acc , F , R > ( & mut self , init : Acc , mut f : F ) -> R
196
+ #[ inline]
197
+ fn rfind < P > ( & mut self , mut predicate : P ) -> Option < Self :: Item >
198
+ where
199
+ P : FnMut ( & Self :: Item ) -> bool ,
200
+ {
201
+ match fuse ! ( self . b. rfind( & mut predicate) ) {
202
+ None => fuse ! ( self . a. rfind( predicate) ) ,
203
+ item => item,
204
+ }
205
+ }
206
+
207
+ fn try_rfold < Acc , F , R > ( & mut self , mut acc : Acc , mut f : F ) -> R
239
208
where
240
209
Self : Sized ,
241
210
F : FnMut ( Acc , Self :: Item ) -> R ,
242
211
R : Try < Ok = Acc > ,
243
212
{
244
- let mut accum = init;
245
- match self . state {
246
- ChainState :: Both | ChainState :: Back => {
247
- accum = self . b . try_rfold ( accum, & mut f) ?;
248
- if let ChainState :: Both = self . state {
249
- self . state = ChainState :: Front ;
250
- }
251
- }
252
- _ => { }
213
+ if let Some ( ref mut b) = self . b {
214
+ acc = b. try_rfold ( acc, & mut f) ?;
215
+ self . b = None ;
253
216
}
254
- if let ChainState :: Front = self . state {
255
- accum = self . a . try_rfold ( accum, & mut f) ?;
217
+ if let Some ( ref mut a) = self . a {
218
+ acc = a. try_rfold ( acc, f) ?;
219
+ self . a = None ;
256
220
}
257
- Try :: from_ok ( accum )
221
+ Try :: from_ok ( acc )
258
222
}
259
223
260
- fn rfold < Acc , F > ( self , init : Acc , mut f : F ) -> Acc
224
+ fn rfold < Acc , F > ( self , mut acc : Acc , mut f : F ) -> Acc
261
225
where
262
226
F : FnMut ( Acc , Self :: Item ) -> Acc ,
263
227
{
264
- let mut accum = init;
265
- match self . state {
266
- ChainState :: Both | ChainState :: Back => {
267
- accum = self . b . rfold ( accum, & mut f) ;
268
- }
269
- _ => { }
228
+ if let Some ( b) = self . b {
229
+ acc = b. rfold ( acc, & mut f) ;
270
230
}
271
- match self . state {
272
- ChainState :: Both | ChainState :: Front => {
273
- accum = self . a . rfold ( accum, & mut f) ;
274
- }
275
- _ => { }
231
+ if let Some ( a) = self . a {
232
+ acc = a. rfold ( acc, f) ;
276
233
}
277
- accum
234
+ acc
278
235
}
279
236
}
280
237
281
238
// Note: *both* must be fused to handle double-ended iterators.
239
+ // Now that we "fuse" both sides, we *could* implement this unconditionally,
240
+ // but we should be cautious about committing to that in the public API.
282
241
#[ stable( feature = "fused" , since = "1.26.0" ) ]
283
242
impl < A , B > FusedIterator for Chain < A , B >
284
243
where
0 commit comments