@@ -68,10 +68,37 @@ impl OverlayedChanges {
68
68
. map ( |x| x. as_ref ( ) . map ( AsRef :: as_ref) )
69
69
}
70
70
71
+ /// Inserts the given key-value pair into the prospective change set.
72
+ ///
73
+ /// `None` can be used to delete a value specified by the given key.
71
74
fn set_storage ( & mut self , key : Vec < u8 > , val : Option < Vec < u8 > > ) {
72
75
self . prospective . insert ( key, val) ;
73
76
}
74
77
78
+ /// Removes all key-value pairs which keys share the given prefix.
79
+ ///
80
+ /// NOTE that this doesn't take place immediately but written into the prospective
81
+ /// change set, and still can be reverted by [`discard_prospective`].
82
+ ///
83
+ /// [`discard_prospective`]: #method.discard_prospective
84
+ fn clear_prefix ( & mut self , prefix : & [ u8 ] ) {
85
+ // Iterate over all prospective and mark all keys that share
86
+ // the given prefix as removed (None).
87
+ for ( key, value) in self . prospective . iter_mut ( ) {
88
+ if key. starts_with ( prefix) {
89
+ * value = None ;
90
+ }
91
+ }
92
+
93
+ // Then do the same with keys from commited changes.
94
+ // NOTE that we are making changes in the prospective change set.
95
+ for key in self . committed . keys ( ) {
96
+ if key. starts_with ( prefix) {
97
+ self . prospective . insert ( key. to_owned ( ) , None ) ;
98
+ }
99
+ }
100
+ }
101
+
75
102
/// Discard prospective changes to state.
76
103
pub fn discard_prospective ( & mut self ) {
77
104
self . prospective . clear ( ) ;
@@ -540,4 +567,44 @@ mod tests {
540
567
assert_eq ! ( remote_result, vec![ 66 ] ) ;
541
568
assert_eq ! ( remote_result, local_result) ;
542
569
}
570
+
571
+ #[ test]
572
+ fn clear_prefix_in_ext_works ( ) {
573
+ let initial: HashMap < _ , _ > = map ! [
574
+ b"aaa" . to_vec( ) => b"0" . to_vec( ) ,
575
+ b"abb" . to_vec( ) => b"1" . to_vec( ) ,
576
+ b"abc" . to_vec( ) => b"2" . to_vec( ) ,
577
+ b"bbb" . to_vec( ) => b"3" . to_vec( )
578
+ ] ;
579
+ let backend = InMemory :: from ( initial) . try_into_trie_backend ( ) . unwrap ( ) ;
580
+ let mut overlay = OverlayedChanges {
581
+ committed : map ! [
582
+ b"aba" . to_vec( ) => Some ( b"1312" . to_vec( ) ) ,
583
+ b"bab" . to_vec( ) => Some ( b"228" . to_vec( ) )
584
+ ] ,
585
+ prospective : map ! [
586
+ b"abd" . to_vec( ) => Some ( b"69" . to_vec( ) ) ,
587
+ b"bbd" . to_vec( ) => Some ( b"42" . to_vec( ) )
588
+ ] ,
589
+ } ;
590
+
591
+ {
592
+ let mut ext = Ext :: new ( & mut overlay, & backend) ;
593
+ ext. clear_prefix ( b"ab" ) ;
594
+ }
595
+ overlay. commit_prospective ( ) ;
596
+
597
+ assert_eq ! (
598
+ overlay. committed,
599
+ map![
600
+ b"abb" . to_vec( ) => None ,
601
+ b"abc" . to_vec( ) => None ,
602
+ b"aba" . to_vec( ) => None ,
603
+ b"abd" . to_vec( ) => None ,
604
+
605
+ b"bab" . to_vec( ) => Some ( b"228" . to_vec( ) ) ,
606
+ b"bbd" . to_vec( ) => Some ( b"42" . to_vec( ) )
607
+ ] ,
608
+ ) ;
609
+ }
543
610
}
0 commit comments