1
1
use crate :: iter:: { InPlaceIterable , Iterator } ;
2
- use crate :: ops:: { ControlFlow , Try } ;
2
+ use crate :: ops:: { ChangeOutputType , ControlFlow , FromResidual , NeverShortCircuit , Residual , Try } ;
3
3
4
4
mod chain;
5
5
mod cloned;
@@ -128,59 +128,62 @@ pub unsafe trait SourceIter {
128
128
}
129
129
130
130
/// An iterator adapter that produces output as long as the underlying
131
- /// iterator produces `Result::Ok` values .
131
+ /// iterator produces values where `Try::branch` says to `ControlFlow::Continue` .
132
132
///
133
- /// If an error is encountered, the iterator stops and the error is
134
- /// stored.
135
- pub ( crate ) struct ResultShunt < ' a , I , E > {
133
+ /// If a `ControlFlow::Break` is encountered, the iterator stops and the
134
+ /// residual is stored.
135
+ pub ( crate ) struct GenericShunt < ' a , I , R > {
136
136
iter : I ,
137
- error : & ' a mut Result < ( ) , E > ,
137
+ residual : & ' a mut Option < R > ,
138
138
}
139
139
140
- /// Process the given iterator as if it yielded a `T` instead of a
141
- /// `Result<T, _>` . Any errors will stop the inner iterator and
142
- /// the overall result will be an error .
143
- pub ( crate ) fn process_results < I , T , E , F , U > ( iter : I , mut f : F ) -> Result < U , E >
140
+ /// Process the given iterator as if it yielded a the item's `Try::Output`
141
+ /// type instead . Any `Try::Residual`s encountered will stop the inner iterator
142
+ /// and be propagated back to the overall result .
143
+ pub ( crate ) fn try_process < I , T , R , F , U > ( iter : I , mut f : F ) -> ChangeOutputType < I :: Item , U >
144
144
where
145
- I : Iterator < Item = Result < T , E > > ,
146
- for < ' a > F : FnMut ( ResultShunt < ' a , I , E > ) -> U ,
145
+ I : Iterator < Item : Try < Output = T , Residual = R > > ,
146
+ for < ' a > F : FnMut ( GenericShunt < ' a , I , R > ) -> U ,
147
+ R : Residual < U > ,
147
148
{
148
- let mut error = Ok ( ( ) ) ;
149
- let shunt = ResultShunt { iter, error : & mut error } ;
149
+ let mut residual = None ;
150
+ let shunt = GenericShunt { iter, residual : & mut residual } ;
150
151
let value = f ( shunt) ;
151
- error. map ( |( ) | value)
152
+ match residual {
153
+ Some ( r) => FromResidual :: from_residual ( r) ,
154
+ None => Try :: from_output ( value) ,
155
+ }
152
156
}
153
157
154
- impl < I , T , E > Iterator for ResultShunt < ' _ , I , E >
158
+ impl < I , R > Iterator for GenericShunt < ' _ , I , R >
155
159
where
156
- I : Iterator < Item = Result < T , E > > ,
160
+ I : Iterator < Item : Try < Residual = R > > ,
157
161
{
158
- type Item = T ;
162
+ type Item = < I :: Item as Try > :: Output ;
159
163
160
164
fn next ( & mut self ) -> Option < Self :: Item > {
161
- self . find ( |_| true )
165
+ self . try_for_each ( ControlFlow :: Break ) . break_value ( )
162
166
}
163
167
164
168
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
165
- if self . error . is_err ( ) {
169
+ if self . residual . is_some ( ) {
166
170
( 0 , Some ( 0 ) )
167
171
} else {
168
172
let ( _, upper) = self . iter . size_hint ( ) ;
169
173
( 0 , upper)
170
174
}
171
175
}
172
176
173
- fn try_fold < B , F , R > ( & mut self , init : B , mut f : F ) -> R
177
+ fn try_fold < B , F , T > ( & mut self , init : B , mut f : F ) -> T
174
178
where
175
- F : FnMut ( B , Self :: Item ) -> R ,
176
- R : Try < Output = B > ,
179
+ F : FnMut ( B , Self :: Item ) -> T ,
180
+ T : Try < Output = B > ,
177
181
{
178
- let error = & mut * self . error ;
179
182
self . iter
180
- . try_fold ( init, |acc, x| match x {
181
- Ok ( x) => ControlFlow :: from_try ( f ( acc, x) ) ,
182
- Err ( e ) => {
183
- * error = Err ( e ) ;
183
+ . try_fold ( init, |acc, x| match Try :: branch ( x ) {
184
+ ControlFlow :: Continue ( x) => ControlFlow :: from_try ( f ( acc, x) ) ,
185
+ ControlFlow :: Break ( r ) => {
186
+ * self . residual = Some ( r ) ;
184
187
ControlFlow :: Break ( try { acc } )
185
188
}
186
189
} )
@@ -192,17 +195,12 @@ where
192
195
Self : Sized ,
193
196
F : FnMut ( B , Self :: Item ) -> B ,
194
197
{
195
- #[ inline]
196
- fn ok < B , T > ( mut f : impl FnMut ( B , T ) -> B ) -> impl FnMut ( B , T ) -> Result < B , !> {
197
- move |acc, x| Ok ( f ( acc, x) )
198
- }
199
-
200
- self . try_fold ( init, ok ( fold) ) . unwrap ( )
198
+ self . try_fold ( init, NeverShortCircuit :: wrap_mut_2 ( fold) ) . 0
201
199
}
202
200
}
203
201
204
202
#[ unstable( issue = "none" , feature = "inplace_iteration" ) ]
205
- unsafe impl < I , E > SourceIter for ResultShunt < ' _ , I , E >
203
+ unsafe impl < I , R > SourceIter for GenericShunt < ' _ , I , R >
206
204
where
207
205
I : SourceIter ,
208
206
{
@@ -215,11 +213,11 @@ where
215
213
}
216
214
}
217
215
218
- // SAFETY: ResultShunt ::next calls I::find , which has to advance `iter` in order to
219
- // return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's guaranteed that
220
- // at least one item will be moved out from the underlying source.
216
+ // SAFETY: GenericShunt ::next calls ` I::try_for_each` , which has to advance `iter`
217
+ // in order to return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's
218
+ // guaranteed that at least one item will be moved out from the underlying source.
221
219
#[ unstable( issue = "none" , feature = "inplace_iteration" ) ]
222
- unsafe impl < I , T , E > InPlaceIterable for ResultShunt < ' _ , I , E > where
223
- I : Iterator < Item = Result < T , E > > + InPlaceIterable
220
+ unsafe impl < I , T , R > InPlaceIterable for GenericShunt < ' _ , I , R > where
221
+ I : Iterator < Item : Try < Output = T , Residual = R > > + InPlaceIterable
224
222
{
225
223
}
0 commit comments