1+ use crate :: iter:: { DoubleEndedIterator , FusedIterator , Iterator , TrustedLen } ;
12use crate :: ops:: Try ;
23use crate :: usize;
34
4- use super :: super :: { DoubleEndedIterator , FusedIterator , Iterator , TrustedLen } ;
5-
65/// An iterator that links two iterators together, in a chain.
76///
87/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its
@@ -14,37 +13,34 @@ use super::super::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
1413#[ must_use = "iterators are lazy and do nothing unless consumed" ]
1514#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1615pub 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 > ,
2023}
2124impl < A , B > Chain < A , B > {
2225 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 ) }
2427 }
2528}
2629
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+ } ;
4844}
4945
5046#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -57,128 +53,99 @@ where
5753
5854 #[ inline]
5955 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,
7059 }
7160 }
7261
7362 #[ inline]
7463 #[ rustc_inherit_overflow_checks]
7564 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 ( ) ,
65+ match self {
66+ Chain { a : Some ( a) , b : Some ( b) } => a. count ( ) + b. count ( ) ,
67+ Chain { a : Some ( a) , b : None } => a. count ( ) ,
68+ Chain { a : None , b : Some ( b) } => b. count ( ) ,
69+ Chain { a : None , b : None } => 0 ,
8070 }
8171 }
8272
83- fn try_fold < Acc , F , R > ( & mut self , init : Acc , mut f : F ) -> R
73+ fn try_fold < Acc , F , R > ( & mut self , mut acc : Acc , mut f : F ) -> R
8474 where
8575 Self : Sized ,
8676 F : FnMut ( Acc , Self :: Item ) -> R ,
8777 R : Try < Ok = Acc > ,
8878 {
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- _ => { }
79+ if let Some ( ref mut a) = self . a {
80+ acc = a. try_fold ( acc, & mut f) ?;
81+ self . a = None ;
9882 }
99- if let ChainState :: Back = self . state {
100- accum = self . b . try_fold ( accum, & mut f) ?;
83+ if let Some ( ref mut b) = self . b {
84+ acc = b. try_fold ( acc, & mut f) ?;
85+ self . b = None ;
10186 }
102- Try :: from_ok ( accum )
87+ Try :: from_ok ( acc )
10388 }
10489
105- fn fold < Acc , F > ( self , init : Acc , mut f : F ) -> Acc
90+ fn fold < Acc , F > ( self , mut acc : Acc , mut f : F ) -> Acc
10691 where
10792 F : FnMut ( Acc , Self :: Item ) -> Acc ,
10893 {
109- let mut accum = init;
110- match self . state {
111- ChainState :: Both | ChainState :: Front => {
112- accum = self . a . fold ( accum, & mut f) ;
113- }
114- _ => { }
94+ if let Some ( a) = self . a {
95+ acc = a. fold ( acc, & mut f) ;
11596 }
116- match self . state {
117- ChainState :: Both | ChainState :: Back => {
118- accum = self . b . fold ( accum, & mut f) ;
119- }
120- _ => { }
97+ if let Some ( b) = self . b {
98+ acc = b. fold ( acc, & mut f) ;
12199 }
122- accum
100+ acc
123101 }
124102
125103 #[ inline]
126104 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 ;
105+ if let Some ( ref mut a) = self . a {
106+ while let Some ( x) = a. next ( ) {
107+ if n == 0 {
108+ return Some ( x) ;
137109 }
110+ n -= 1 ;
138111 }
139- ChainState :: Back => { }
112+ self . a = None ;
140113 }
141- if let ChainState :: Back = self . state { self . b . nth ( n) } else { None }
114+ fuse ! ( self . b. nth( n) )
142115 }
143116
144117 #[ inline]
145118 fn find < P > ( & mut self , mut predicate : P ) -> Option < Self :: Item >
146119 where
147120 P : FnMut ( & Self :: Item ) -> bool ,
148121 {
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) ,
122+ match fuse ! ( self . a. find( & mut predicate) ) {
123+ None => fuse ! ( self . b. find( predicate) ) ,
124+ item => item,
159125 }
160126 }
161127
162128 #[ inline]
163129 fn last ( self ) -> Option < A :: Item > {
164- match self . state {
165- ChainState :: Both => {
130+ match self {
131+ Chain { a : Some ( a ) , b : Some ( b ) } => {
166132 // Must exhaust a before b.
167- let a_last = self . a . last ( ) ;
168- let b_last = self . b . last ( ) ;
133+ let a_last = a. last ( ) ;
134+ let b_last = b. last ( ) ;
169135 b_last. or ( a_last)
170136 }
171- ChainState :: Front => self . a . last ( ) ,
172- ChainState :: Back => self . b . last ( ) ,
137+ Chain { a : Some ( a) , b : None } => a. last ( ) ,
138+ Chain { a : None , b : Some ( b) } => b. last ( ) ,
139+ Chain { a : None , b : None } => None ,
173140 }
174141 }
175142
176143 #[ inline]
177144 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 ( ) ;
145+ match self {
146+ Chain { a : Some ( a ) , b : Some ( b ) } => {
147+ let ( a_lower, a_upper) = a. size_hint ( ) ;
148+ let ( b_lower, b_upper) = b. size_hint ( ) ;
182149
183150 let lower = a_lower. saturating_add ( b_lower) ;
184151
@@ -189,8 +156,9 @@ where
189156
190157 ( lower, upper)
191158 }
192- ChainState :: Front => self . a . size_hint ( ) ,
193- ChainState :: Back => self . b . size_hint ( ) ,
159+ Chain { a : Some ( a) , b : None } => a. size_hint ( ) ,
160+ Chain { a : None , b : Some ( b) } => b. size_hint ( ) ,
161+ Chain { a : None , b : None } => ( 0 , Some ( 0 ) ) ,
194162 }
195163 }
196164}
@@ -203,82 +171,71 @@ where
203171{
204172 #[ inline]
205173 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 ( ) ,
174+ match fuse ! ( self . b. next_back( ) ) {
175+ None => fuse ! ( self . a. next_back( ) ) ,
176+ item => item,
216177 }
217178 }
218179
219180 #[ inline]
220181 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 ;
182+ if let Some ( ref mut b) = self . b {
183+ while let Some ( x) = b. next_back ( ) {
184+ if n == 0 {
185+ return Some ( x) ;
231186 }
187+ n -= 1 ;
232188 }
233- ChainState :: Front => { }
189+ self . b = None ;
190+ }
191+ fuse ! ( self . a. nth_back( n) )
192+ }
193+
194+ #[ inline]
195+ fn rfind < P > ( & mut self , mut predicate : P ) -> Option < Self :: Item >
196+ where
197+ P : FnMut ( & Self :: Item ) -> bool ,
198+ {
199+ match fuse ! ( self . b. rfind( & mut predicate) ) {
200+ None => fuse ! ( self . a. rfind( predicate) ) ,
201+ item => item,
234202 }
235- if let ChainState :: Front = self . state { self . a . nth_back ( n) } else { None }
236203 }
237204
238- fn try_rfold < Acc , F , R > ( & mut self , init : Acc , mut f : F ) -> R
205+ fn try_rfold < Acc , F , R > ( & mut self , mut acc : Acc , mut f : F ) -> R
239206 where
240207 Self : Sized ,
241208 F : FnMut ( Acc , Self :: Item ) -> R ,
242209 R : Try < Ok = Acc > ,
243210 {
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- _ => { }
211+ if let Some ( ref mut b) = self . b {
212+ acc = b. try_rfold ( acc, & mut f) ?;
213+ self . b = None ;
253214 }
254- if let ChainState :: Front = self . state {
255- accum = self . a . try_rfold ( accum, & mut f) ?;
215+ if let Some ( ref mut a) = self . a {
216+ acc = a. try_rfold ( acc, f) ?;
217+ self . a = None ;
256218 }
257- Try :: from_ok ( accum )
219+ Try :: from_ok ( acc )
258220 }
259221
260- fn rfold < Acc , F > ( self , init : Acc , mut f : F ) -> Acc
222+ fn rfold < Acc , F > ( self , mut acc : Acc , mut f : F ) -> Acc
261223 where
262224 F : FnMut ( Acc , Self :: Item ) -> Acc ,
263225 {
264- let mut accum = init;
265- match self . state {
266- ChainState :: Both | ChainState :: Back => {
267- accum = self . b . rfold ( accum, & mut f) ;
268- }
269- _ => { }
226+ if let Some ( b) = self . b {
227+ acc = b. rfold ( acc, & mut f) ;
270228 }
271- match self . state {
272- ChainState :: Both | ChainState :: Front => {
273- accum = self . a . rfold ( accum, & mut f) ;
274- }
275- _ => { }
229+ if let Some ( a) = self . a {
230+ acc = a. rfold ( acc, f) ;
276231 }
277- accum
232+ acc
278233 }
279234}
280235
281236// Note: *both* must be fused to handle double-ended iterators.
237+ // Now that we "fuse" both sides, we *could* implement this unconditionally,
238+ // but we should be cautious about committing to that in the public API.
282239#[ stable( feature = "fused" , since = "1.26.0" ) ]
283240impl < A , B > FusedIterator for Chain < A , B >
284241where
0 commit comments