@@ -184,7 +184,7 @@ pub trait Iterator {
184
184
fn chain < U > ( self , other : U ) -> Chain < Self , U :: IntoIter > where
185
185
Self : Sized , U : IntoIterator < Item =Self :: Item > ,
186
186
{
187
- Chain { a : self , b : other. into_iter ( ) , flag : false }
187
+ Chain { a : self , b : other. into_iter ( ) , state : ChainState :: Both }
188
188
}
189
189
190
190
/// Creates an iterator that iterates over both this and the specified
@@ -1277,7 +1277,30 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
1277
1277
pub struct Chain < A , B > {
1278
1278
a : A ,
1279
1279
b : B ,
1280
- flag : bool ,
1280
+ state : ChainState ,
1281
+ }
1282
+
1283
+ // The iterator protocol specifies that iteration ends with the return value
1284
+ // `None` from `.next()` (or `.next_back()`) and it is unspecified what
1285
+ // further calls return. The chain adaptor must account for this since it uses
1286
+ // two subiterators.
1287
+ //
1288
+ // It uses three states:
1289
+ //
1290
+ // - Both: `a` and `b` are remaining
1291
+ // - Front: `a` remaining
1292
+ // - Back: `b` remaining
1293
+ //
1294
+ // The fourth state (neither iterator is remaining) only occurs after Chain has
1295
+ // returned None once, so we don't need to store this state.
1296
+ #[ derive( Clone ) ]
1297
+ enum ChainState {
1298
+ // both front and back iterator are remaining
1299
+ Both ,
1300
+ // only front is remaining
1301
+ Front ,
1302
+ // only back is remaining
1303
+ Back ,
1281
1304
}
1282
1305
1283
1306
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1289,42 +1312,58 @@ impl<A, B> Iterator for Chain<A, B> where
1289
1312
1290
1313
#[ inline]
1291
1314
fn next ( & mut self ) -> Option < A :: Item > {
1292
- if self . flag {
1293
- self . b . next ( )
1294
- } else {
1295
- match self . a . next ( ) {
1296
- Some ( x) => return Some ( x) ,
1297
- _ => ( )
1298
- }
1299
- self . flag = true ;
1300
- self . b . next ( )
1315
+ match self . state {
1316
+ ChainState :: Both => match self . a . next ( ) {
1317
+ elt @ Some ( ..) => return elt,
1318
+ None => {
1319
+ self . state = ChainState :: Back ;
1320
+ self . b . next ( )
1321
+ }
1322
+ } ,
1323
+ ChainState :: Front => self . a . next ( ) ,
1324
+ ChainState :: Back => self . b . next ( ) ,
1301
1325
}
1302
1326
}
1303
1327
1304
1328
#[ inline]
1305
1329
fn count ( self ) -> usize {
1306
- ( if !self . flag { self . a . count ( ) } else { 0 } ) + self . b . count ( )
1330
+ match self . state {
1331
+ ChainState :: Both => self . a . count ( ) + self . b . count ( ) ,
1332
+ ChainState :: Front => self . a . count ( ) ,
1333
+ ChainState :: Back => self . b . count ( ) ,
1334
+ }
1307
1335
}
1308
1336
1309
1337
#[ inline]
1310
1338
fn nth ( & mut self , mut n : usize ) -> Option < A :: Item > {
1311
- if !self . flag {
1312
- for x in self . a . by_ref ( ) {
1313
- if n == 0 {
1314
- return Some ( x)
1339
+ match self . state {
1340
+ ChainState :: Both | ChainState :: Front => {
1341
+ for x in self . a . by_ref ( ) {
1342
+ if n == 0 {
1343
+ return Some ( x)
1344
+ }
1345
+ n -= 1 ;
1346
+ }
1347
+ if let ChainState :: Both = self . state {
1348
+ self . state = ChainState :: Back ;
1315
1349
}
1316
- n -= 1 ;
1317
1350
}
1318
- self . flag = true ;
1351
+ ChainState :: Back => { }
1352
+ }
1353
+ if let ChainState :: Back = self . state {
1354
+ self . b . nth ( n)
1355
+ } else {
1356
+ None
1319
1357
}
1320
- self . b . nth ( n)
1321
1358
}
1322
1359
1323
1360
#[ inline]
1324
1361
fn last ( self ) -> Option < A :: Item > {
1325
- let a_last = if self . flag { None } else { self . a . last ( ) } ;
1326
- let b_last = self . b . last ( ) ;
1327
- b_last. or ( a_last)
1362
+ match self . state {
1363
+ ChainState :: Both => self . b . last ( ) . or ( self . a . last ( ) ) ,
1364
+ ChainState :: Front => self . a . last ( ) ,
1365
+ ChainState :: Back => self . b . last ( )
1366
+ }
1328
1367
}
1329
1368
1330
1369
#[ inline]
@@ -1350,9 +1389,16 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
1350
1389
{
1351
1390
#[ inline]
1352
1391
fn next_back ( & mut self ) -> Option < A :: Item > {
1353
- match self . b . next_back ( ) {
1354
- Some ( x) => Some ( x) ,
1355
- None => self . a . next_back ( )
1392
+ match self . state {
1393
+ ChainState :: Both => match self . b . next_back ( ) {
1394
+ elt @ Some ( ..) => return elt,
1395
+ None => {
1396
+ self . state = ChainState :: Front ;
1397
+ self . a . next_back ( )
1398
+ }
1399
+ } ,
1400
+ ChainState :: Front => self . a . next_back ( ) ,
1401
+ ChainState :: Back => self . b . next_back ( ) ,
1356
1402
}
1357
1403
}
1358
1404
}
0 commit comments