11use crate :: iter:: { InPlaceIterable , Iterator } ;
2- use crate :: ops:: { ControlFlow , Try } ;
2+ use crate :: ops:: { ChangeOutputType , ControlFlow , FromResidual , NeverShortCircuit , Residual , Try } ;
33
44mod chain;
55mod cloned;
@@ -128,59 +128,62 @@ pub unsafe trait SourceIter {
128128}
129129
130130/// 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` .
132132///
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 > {
136136 iter : I ,
137- error : & ' a mut Result < ( ) , E > ,
137+ residual : & ' a mut Option < R > ,
138138}
139139
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 >
144144where
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 > ,
147148{
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 } ;
150151 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+ }
152156}
153157
154- impl < I , T , E > Iterator for ResultShunt < ' _ , I , E >
158+ impl < I , R > Iterator for GenericShunt < ' _ , I , R >
155159where
156- I : Iterator < Item = Result < T , E > > ,
160+ I : Iterator < Item : Try < Residual = R > > ,
157161{
158- type Item = T ;
162+ type Item = < I :: Item as Try > :: Output ;
159163
160164 fn next ( & mut self ) -> Option < Self :: Item > {
161- self . find ( |_| true )
165+ self . try_for_each ( ControlFlow :: Break ) . break_value ( )
162166 }
163167
164168 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
165- if self . error . is_err ( ) {
169+ if self . residual . is_some ( ) {
166170 ( 0 , Some ( 0 ) )
167171 } else {
168172 let ( _, upper) = self . iter . size_hint ( ) ;
169173 ( 0 , upper)
170174 }
171175 }
172176
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
174178 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 > ,
177181 {
178- let error = & mut * self . error ;
179182 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 ) ;
184187 ControlFlow :: Break ( try { acc } )
185188 }
186189 } )
@@ -192,17 +195,12 @@ where
192195 Self : Sized ,
193196 F : FnMut ( B , Self :: Item ) -> B ,
194197 {
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
201199 }
202200}
203201
204202#[ 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 >
206204where
207205 I : SourceIter ,
208206{
@@ -215,11 +213,11 @@ where
215213 }
216214}
217215
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.
221219#[ 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
224222{
225223}
0 commit comments