@@ -9,6 +9,7 @@ use futures::{
99} ;
1010use pin_project:: pin_project;
1111use std:: {
12+ collections:: VecDeque ,
1213 future:: Future ,
1314 pin:: Pin ,
1415 sync:: Arc ,
@@ -22,6 +23,39 @@ pub trait Ancestry<B: Block>: Stream<Item = B> + Send + Unpin + 'static {
2223 fn peek ( & self ) -> Option < & B > ;
2324}
2425
26+ /// Creates an ancestry stream from a fixed sequence of blocks.
27+ ///
28+ /// Blocks are yielded in iterator order and no parent fetching is performed. This is useful when
29+ /// the caller already has the complete ancestry needed by an application.
30+ pub fn from_iter < B > ( blocks : impl IntoIterator < Item = B > ) -> impl Ancestry < B >
31+ where
32+ B : Block ,
33+ {
34+ BoundedAncestry {
35+ blocks : blocks. into_iter ( ) . collect ( ) ,
36+ }
37+ }
38+
39+ struct BoundedAncestry < B : Block > {
40+ blocks : VecDeque < B > ,
41+ }
42+
43+ impl < B : Block > Unpin for BoundedAncestry < B > { }
44+
45+ impl < B : Block > Ancestry < B > for BoundedAncestry < B > {
46+ fn peek ( & self ) -> Option < & B > {
47+ self . blocks . front ( )
48+ }
49+ }
50+
51+ impl < B : Block > Stream for BoundedAncestry < B > {
52+ type Item = B ;
53+
54+ fn poll_next ( mut self : Pin < & mut Self > , _: & mut Context < ' _ > ) -> Poll < Option < Self :: Item > > {
55+ Poll :: Ready ( self . blocks . pop_front ( ) )
56+ }
57+ }
58+
2559/// An interface for providing parent blocks.
2660pub trait BlockProvider : Send + ' static {
2761 /// The block type the provider walks.
@@ -384,6 +418,34 @@ mod test {
384418 } ) ;
385419 }
386420
421+ #[ test]
422+ fn test_from_iter_available_through_ancestry_trait ( ) {
423+ fn peek_height ( ancestry : impl Ancestry < Block < Sha256Digest , ( ) > > ) -> Option < Height > {
424+ ancestry. peek ( ) . map ( Heightable :: height)
425+ }
426+
427+ let block = Block :: new :: < Sha256 > ( ( ) , Sha256Digest :: EMPTY , Height :: new ( 1 ) , 1 ) ;
428+ let ancestry = from_iter ( [ block. clone ( ) ] ) ;
429+
430+ assert_eq ! ( peek_height( ancestry) , Some ( block. height( ) ) ) ;
431+ }
432+
433+ #[ test]
434+ fn test_from_iter_yields_blocks_in_order_and_peeks_next ( ) {
435+ deterministic:: Runner :: default ( ) . start ( |_| async move {
436+ let parent = Block :: new :: < Sha256 > ( ( ) , Sha256Digest :: EMPTY , Height :: new ( 1 ) , 1 ) ;
437+ let child = Block :: new :: < Sha256 > ( ( ) , parent. digest ( ) , Height :: new ( 2 ) , 2 ) ;
438+ let mut ancestry = from_iter ( [ child. clone ( ) , parent. clone ( ) ] ) ;
439+
440+ assert_eq ! ( ancestry. peek( ) , Some ( & child) ) ;
441+ assert_eq ! ( ancestry. next( ) . await , Some ( child) ) ;
442+ assert_eq ! ( ancestry. peek( ) , Some ( & parent) ) ;
443+ assert_eq ! ( ancestry. next( ) . await , Some ( parent) ) ;
444+ assert_eq ! ( ancestry. peek( ) , None ) ;
445+ assert_eq ! ( ancestry. next( ) . await , None ) ;
446+ } ) ;
447+ }
448+
387449 #[ test]
388450 fn test_yields_genesis_and_stops ( ) {
389451 deterministic:: Runner :: default ( ) . start ( |context| async move {
0 commit comments