1010 core:: fmt:: Formatter ,
1111 derive_more:: { From , Into } ,
1212 smallvec:: { SmallVec , smallvec} ,
13- std:: sync:: Arc ,
13+ std:: { cmp :: min , sync:: Arc } ,
1414} ;
1515
1616/// Represents a path to a step or a nested pipeline in a pipeline.
2424#[ derive( PartialEq , Eq , Clone , From , Into , Hash ) ]
2525pub ( crate ) struct StepPath ( SmallVec < [ usize ; 8 ] > ) ;
2626
27+ const EXTRA_SECTIONS_SIZE : usize = 1024 ;
2728const PROLOGUE_INDEX : usize = usize:: MIN ;
28- const EPILOGUE_START_INDEX : usize = usize :: MAX - 1024 ; // Reserve space for epilogue steps
29- const STEP0_INDEX : usize = PROLOGUE_INDEX + 1 ;
29+ const STEP0_INDEX : usize = PROLOGUE_INDEX + EXTRA_SECTIONS_SIZE + 1 ;
30+ const EPILOGUE_START_INDEX : usize = usize :: MAX - EXTRA_SECTIONS_SIZE ;
3031
3132/// Public API
3233impl StepPath {
@@ -81,7 +82,7 @@ impl StepPath {
8182
8283 /// Returns `true` if the path is pointing to a prologue of a pipeline.
8384 pub ( crate ) fn is_prologue ( & self ) -> bool {
84- self . leaf ( ) == PROLOGUE_INDEX
85+ self . leaf ( ) < STEP0_INDEX
8586 }
8687
8788 /// Returns `true` if the path is pointing to an epilogue of a pipeline.
@@ -227,30 +228,44 @@ impl StepPath {
227228///
228229/// None of those methods do any checks on the validity of the path.
229230impl StepPath {
230- /// Returns a step path that points to the prologue step.
231- pub ( in crate :: pipelines) fn prologue ( ) -> Self {
232- Self ( smallvec ! [ PROLOGUE_INDEX ] )
231+ /// Returns a leaf step path pointing at a specific prologue step with the
232+ /// given index.
233+ pub ( in crate :: pipelines) fn prologue_step ( prologue_index : usize ) -> Self {
234+ Self ( smallvec ! [ min(
235+ prologue_index + PROLOGUE_INDEX ,
236+ STEP0_INDEX - 1 ,
237+ ) ] )
233238 }
234239
235- /// Returns a leaf step path pointing at the first epilogue step.
236- pub ( in crate :: pipelines) fn epilogue ( ) -> Self {
237- Self :: epilogue_step ( 0 )
240+ /// Returns a step path that points to the first prologue step.
241+ pub ( in crate :: pipelines) fn prologue ( ) -> Self {
242+ Self :: prologue_step ( 0 )
238243 }
239244
240245 /// Returns a leaf step path pointing at a specific epilogue step with the
241246 /// given index.
242247 pub ( in crate :: pipelines) fn epilogue_step ( epilogue_index : usize ) -> Self {
243- Self ( smallvec ! [ epilogue_index + EPILOGUE_START_INDEX ] )
248+ Self ( smallvec ! [
249+ epilogue_index. saturating_add( EPILOGUE_START_INDEX )
250+ ] )
244251 }
245252
246- /// Returns a new step path that points to the first non-prologue step.
247- pub ( in crate :: pipelines) fn step0 ( ) -> Self {
248- Self :: step ( 0 )
253+ /// Returns a leaf step path pointing at the first epilogue step.
254+ pub ( in crate :: pipelines) fn epilogue ( ) -> Self {
255+ Self :: epilogue_step ( 0 )
249256 }
250257
251258 /// Returns a leaf step path pointing at a step with the given index.
252259 pub ( in crate :: pipelines) fn step ( step_index : usize ) -> Self {
253- Self ( smallvec ! [ step_index + STEP0_INDEX ] )
260+ Self ( smallvec ! [ min(
261+ step_index + STEP0_INDEX ,
262+ EPILOGUE_START_INDEX - 1
263+ ) ] )
264+ }
265+
266+ /// Returns a new step path that points to the first non-prologue step.
267+ pub ( in crate :: pipelines) fn step0 ( ) -> Self {
268+ Self :: step ( 0 )
254269 }
255270
256271 /// Appends a new path to the current path.
@@ -280,20 +295,22 @@ impl core::fmt::Display for StepPath {
280295
281296 if let Some ( & first) = iter. next ( ) {
282297 match first {
283- PROLOGUE_INDEX => write ! ( f, "p" ) ,
298+ idx if idx < STEP0_INDEX => write ! ( f, "p{}" , idx - PROLOGUE_INDEX ) ,
284299 idx if idx >= EPILOGUE_START_INDEX => {
285300 write ! ( f, "e{}" , idx - EPILOGUE_START_INDEX )
286301 }
287- index => write ! ( f, "{index}" ) ,
302+ idx => write ! ( f, "{}" , idx - STEP0_INDEX ) ,
288303 } ?;
289304
290305 for & index in iter {
291306 match index {
292- PROLOGUE_INDEX => write ! ( f, "_p" ) ,
307+ idx if idx < STEP0_INDEX => {
308+ write ! ( f, "_p{}" , idx - PROLOGUE_INDEX )
309+ }
293310 idx if idx >= EPILOGUE_START_INDEX => {
294311 write ! ( f, "_e{}" , idx - EPILOGUE_START_INDEX )
295312 }
296- index => write ! ( f, "_{index}" ) ,
313+ idx => write ! ( f, "_{}" , idx - STEP0_INDEX ) ,
297314 } ?;
298315 }
299316 }
@@ -325,7 +342,7 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
325342 /// Given a pipeline, returns a navigator that points at the first executable
326343 /// item in the pipeline.
327344 ///
328- /// In pipelines with a prologue, this will point to the prologue step.
345+ /// In pipelines with a prologue, this will point to the first prologue step.
329346 /// In pipelines without a prologue, this will point to the first step.
330347 /// In pipelines with no steps, but with an epilogue, this will point to the
331348 /// first epilogue step.
@@ -340,8 +357,8 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
340357 }
341358
342359 // pipeline has a prologue, return it.
343- if pipeline. prologue ( ) . is_some ( ) {
344- return Some ( Self ( StepPath :: prologue ( ) , vec ! [ pipeline] ) ) ;
360+ if ! pipeline. prologue ( ) . is_empty ( ) {
361+ return Self ( StepPath :: prologue ( ) , vec ! [ pipeline] ) . enter ( ) ;
345362 }
346363
347364 // pipeline has no prologue
@@ -369,6 +386,11 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
369386 if self . is_prologue ( ) {
370387 enclosing_pipeline
371388 . prologue ( )
389+ . get (
390+ step_index
391+ . checked_sub ( PROLOGUE_INDEX )
392+ . expect ( "step index should be >= prologue index" ) ,
393+ )
372394 . expect ( "Step path points to a non-existing prologue" )
373395 } else if self . is_epilogue ( ) {
374396 enclosing_pipeline
@@ -419,9 +441,10 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
419441 ///
420442 /// Returns `None` if there are no more steps to execute in the pipeline.
421443 pub ( crate ) fn next_ok ( self ) -> Option < Self > {
444+ let enclosing_pipeline = self . pipeline ( ) ;
445+
422446 if self . is_epilogue ( ) {
423447 // we are in an epilogue step, check if there are more epilogue steps
424- let enclosing_pipeline = self . pipeline ( ) ;
425448 let epilogue_index = self
426449 . 0
427450 . leaf ( )
@@ -437,12 +460,22 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
437460 }
438461
439462 if self . is_prologue ( ) {
440- // start looping (if possible)
463+ // we are in a prologue step, check if there are more prologue steps
464+ let prologue_index = self
465+ . 0
466+ . leaf ( )
467+ . checked_sub ( PROLOGUE_INDEX )
468+ . expect ( "invalid prologue step index in the step path" ) ;
469+
470+ if prologue_index + 1 < enclosing_pipeline. prologue . len ( ) {
471+ // there are more prologue step, go to the next one
472+ return Self ( self . 0 . increment_leaf ( ) , self . 1 . clone ( ) ) . enter ( ) ;
473+ }
474+
475+ // this is the last prologue step, enter step section
441476 return self . after_prologue ( ) ;
442477 }
443478
444- let enclosing_pipeline = self . pipeline ( ) ;
445-
446479 // we are in a regular step.
447480 assert ! (
448481 !enclosing_pipeline. steps( ) . is_empty( ) ,
@@ -480,7 +513,8 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
480513 ///
481514 /// Returns `None` if there are no more steps to execute in the pipeline.
482515 pub ( crate ) fn next_break ( self ) -> Option < Self > {
483- if self . is_epilogue ( ) {
516+ // breaking in prologue or epilogue directly stop pipeline execution
517+ if self . is_epilogue ( ) || self . is_prologue ( ) {
484518 // the loop is over.
485519 return self . next_in_parent ( ) ;
486520 }
@@ -553,7 +587,7 @@ impl<P: Platform> StepNavigator<'_, P> {
553587
554588 if path. is_prologue ( ) {
555589 assert ! (
556- enclosing_pipeline. prologue( ) . is_some ( ) ,
590+ ! enclosing_pipeline. prologue( ) . is_empty ( ) ,
557591 "path is prologue, but the enclosing pipeline has none" ,
558592 ) ;
559593 // if we are in a prologue, we can just return ourselves.
@@ -673,6 +707,7 @@ mod test {
673707
674708 fake_step ! ( Prologue1 ) ;
675709 fake_step ! ( Prologue2 ) ;
710+ fake_step ! ( Prologue3 ) ;
676711
677712 fake_step ! ( Step1 ) ;
678713 fake_step ! ( Step2 ) ;
@@ -704,6 +739,7 @@ mod test {
704739 ( StepX , StepY , StepZ )
705740 . with_name ( "nested1.1" )
706741 . with_prologue ( Prologue2 )
742+ . with_prologue ( Prologue3 )
707743 . with_epilogue ( Epilogue2 ) ,
708744 )
709745 . with_step ( StepC )
@@ -724,6 +760,10 @@ mod test {
724760 self . concat ( StepPath :: prologue ( ) )
725761 }
726762
763+ fn append_prologue_step ( self , step_index : usize ) -> Self {
764+ self . concat ( StepPath :: prologue_step ( step_index) )
765+ }
766+
727767 fn append_epilogue ( self ) -> Self {
728768 self . concat ( StepPath :: epilogue ( ) )
729769 }
@@ -787,7 +827,7 @@ mod test {
787827 vec![ "one" , "two" ]
788828 ) ;
789829
790- // one nested step with prologue
830+ // one nested step with a one-step prologue
791831 assert_entrypoint ! (
792832 Pipeline :: <Ethereum >:: named( "one" ) . with_pipeline(
793833 Loop ,
@@ -905,7 +945,16 @@ mod test {
905945 assert_eq ! ( cursor. 0 , StepPath :: step( 2 ) . append_step( 0 ) ) ;
906946
907947 let cursor = cursor. next_ok ( ) . unwrap ( ) ;
908- assert_eq ! ( cursor. 0 , StepPath :: step( 2 ) . append_step( 1 ) . append_prologue( ) ) ;
948+ assert_eq ! (
949+ cursor. 0 ,
950+ StepPath :: step( 2 ) . append_step( 1 ) . append_prologue_step( 0 )
951+ ) ;
952+
953+ let cursor = cursor. next_ok ( ) . unwrap ( ) ;
954+ assert_eq ! (
955+ cursor. 0 ,
956+ StepPath :: step( 2 ) . append_step( 1 ) . append_prologue_step( 1 )
957+ ) ;
909958
910959 let cursor = cursor. next_ok ( ) . unwrap ( ) ;
911960 assert_eq ! ( cursor. 0 , StepPath :: step( 2 ) . append_step( 1 ) . append_step( 0 ) ) ;
@@ -947,12 +996,12 @@ mod test {
947996 assert_eq ! ( cursor. 0 , StepPath :: step( 2 ) . append_step( 0 ) ) ;
948997
949998 let cursor = cursor. next_ok ( ) . unwrap ( ) ;
950- assert_eq ! ( cursor. 0 , StepPath :: step( 2 ) . append_step( 1 ) . append_prologue( ) ) ;
999+ assert_eq ! (
1000+ cursor. 0 ,
1001+ StepPath :: step( 2 ) . append_step( 1 ) . append_prologue_step( 0 )
1002+ ) ;
9511003
9521004 let cursor = cursor. next_break ( ) . unwrap ( ) ;
953- assert_eq ! ( cursor. 0 , StepPath :: step( 2 ) . append_step( 1 ) . append_epilogue( ) ) ;
954-
955- let cursor = cursor. next_ok ( ) . unwrap ( ) ;
9561005 assert_eq ! ( cursor. 0 , StepPath :: step( 2 ) . append_step( 2 ) ) ;
9571006
9581007 let cursor = cursor. next_break ( ) . unwrap ( ) ;
@@ -998,12 +1047,15 @@ mod test {
9981047 assert_eq ! ( navigator. instance( ) . name( ) , cursor. instance( ) . name( ) ) ;
9991048
10001049 let cursor = cursor. next_ok ( ) . unwrap ( ) ;
1001- assert_eq ! ( cursor. 0 , StepPath :: step( 2 ) . append_step( 1 ) . append_prologue( ) ) ;
1050+ assert_eq ! (
1051+ cursor. 0 ,
1052+ StepPath :: step( 2 ) . append_step( 1 ) . append_prologue_step( 0 )
1053+ ) ;
10021054 let navigator = cursor. 0 . navigator ( & pipeline) . unwrap ( ) ;
10031055 assert_eq ! ( navigator. 1 . len( ) , cursor. 1 . len( ) ) ;
10041056 assert_eq ! (
10051057 navigator. 0 ,
1006- StepPath :: step( 2 ) . append_step( 1 ) . append_prologue ( )
1058+ StepPath :: step( 2 ) . append_step( 1 ) . append_prologue_step ( 0 )
10071059 ) ;
10081060 assert_eq ! ( navigator. instance( ) . name( ) , cursor. instance( ) . name( ) ) ;
10091061
0 commit comments