@@ -213,6 +213,9 @@ impl Default for Pays {
213
213
}
214
214
215
215
/// A generalized group of dispatch types.
216
+ ///
217
+ /// NOTE whenever upgrading the enum make sure to also update
218
+ /// [DispatchClass::all] and [DispatchClass::non_mandatory] helper functions.
216
219
#[ cfg_attr( feature = "std" , derive( Serialize , Deserialize ) ) ]
217
220
#[ cfg_attr( feature = "std" , serde( rename_all = "camelCase" ) ) ]
218
221
#[ derive( PartialEq , Eq , Clone , Copy , Encode , Decode , RuntimeDebug ) ]
@@ -242,6 +245,39 @@ impl Default for DispatchClass {
242
245
}
243
246
}
244
247
248
+ impl DispatchClass {
249
+ /// Returns an array containing all dispatch classes.
250
+ pub fn all ( ) -> & ' static [ DispatchClass ] {
251
+ & [ DispatchClass :: Normal , DispatchClass :: Operational , DispatchClass :: Mandatory ]
252
+ }
253
+
254
+ /// Returns an array of all dispatch classes except `Mandatory`.
255
+ pub fn non_mandatory ( ) -> & ' static [ DispatchClass ] {
256
+ & [ DispatchClass :: Normal , DispatchClass :: Operational ]
257
+ }
258
+ }
259
+
260
+ /// A trait that represents one or many values of given type.
261
+ ///
262
+ /// Useful to accept as parameter type to let the caller pass either a single value directly
263
+ /// or an iterator.
264
+ pub trait OneOrMany < T > {
265
+ /// The iterator type.
266
+ type Iter : Iterator < Item = T > ;
267
+ /// Convert this item into an iterator.
268
+ fn into_iter ( self ) -> Self :: Iter ;
269
+ }
270
+
271
+ impl OneOrMany < DispatchClass > for DispatchClass {
272
+ type Iter = sp_std:: iter:: Once < DispatchClass > ;
273
+ fn into_iter ( self ) -> Self :: Iter { sp_std:: iter:: once ( self ) }
274
+ }
275
+
276
+ impl < ' a > OneOrMany < DispatchClass > for & ' a [ DispatchClass ] {
277
+ type Iter = sp_std:: iter:: Cloned < sp_std:: slice:: Iter < ' a , DispatchClass > > ;
278
+ fn into_iter ( self ) -> Self :: Iter { self . iter ( ) . cloned ( ) }
279
+ }
280
+
245
281
/// Primitives related to priority management of Frame.
246
282
pub mod priority {
247
283
/// The starting point of all Operational transactions. 3/4 of u64::max_value().
@@ -695,6 +731,87 @@ impl<T> WeightToFeePolynomial for IdentityFee<T> where
695
731
}
696
732
}
697
733
734
+ /// A struct holding value for each `DispatchClass`.
735
+ #[ derive( Clone , Eq , PartialEq , Default , RuntimeDebug , Encode , Decode ) ]
736
+ pub struct PerDispatchClass < T > {
737
+ /// Value for `Normal` extrinsics.
738
+ normal : T ,
739
+ /// Value for `Operational` extrinsics.
740
+ operational : T ,
741
+ /// Value for `Mandatory` extrinsics.
742
+ mandatory : T ,
743
+ }
744
+
745
+ impl < T > PerDispatchClass < T > {
746
+ /// Create new `PerDispatchClass` with the same value for every class.
747
+ pub fn new ( val : impl Fn ( DispatchClass ) -> T ) -> Self {
748
+ Self {
749
+ normal : val ( DispatchClass :: Normal ) ,
750
+ operational : val ( DispatchClass :: Operational ) ,
751
+ mandatory : val ( DispatchClass :: Mandatory ) ,
752
+ }
753
+ }
754
+
755
+ /// Get a mutable reference to current value of given class.
756
+ pub fn get_mut ( & mut self , class : DispatchClass ) -> & mut T {
757
+ match class {
758
+ DispatchClass :: Operational => & mut self . operational ,
759
+ DispatchClass :: Normal => & mut self . normal ,
760
+ DispatchClass :: Mandatory => & mut self . mandatory ,
761
+ }
762
+ }
763
+
764
+ /// Get current value for given class.
765
+ pub fn get ( & self , class : DispatchClass ) -> & T {
766
+ match class {
767
+ DispatchClass :: Normal => & self . normal ,
768
+ DispatchClass :: Operational => & self . operational ,
769
+ DispatchClass :: Mandatory => & self . mandatory ,
770
+ }
771
+ }
772
+ }
773
+
774
+ impl < T : Clone > PerDispatchClass < T > {
775
+ /// Set the value of given class.
776
+ pub fn set ( & mut self , new : T , class : impl OneOrMany < DispatchClass > ) {
777
+ for class in class. into_iter ( ) {
778
+ * self . get_mut ( class) = new. clone ( ) ;
779
+ }
780
+ }
781
+ }
782
+
783
+ impl PerDispatchClass < Weight > {
784
+ /// Returns the total weight consumed by all extrinsics in the block.
785
+ pub fn total ( & self ) -> Weight {
786
+ let mut sum = 0 ;
787
+ for class in DispatchClass :: all ( ) {
788
+ sum = sum. saturating_add ( * self . get ( * class) ) ;
789
+ }
790
+ sum
791
+ }
792
+
793
+ /// Add some weight of a specific dispatch class, saturating at the numeric bounds of `Weight`.
794
+ pub fn add ( & mut self , weight : Weight , class : DispatchClass ) {
795
+ let value = self . get_mut ( class) ;
796
+ * value = value. saturating_add ( weight) ;
797
+ }
798
+
799
+ /// Try to add some weight of a specific dispatch class, returning Err(()) if overflow would
800
+ /// occur.
801
+ pub fn checked_add ( & mut self , weight : Weight , class : DispatchClass ) -> Result < ( ) , ( ) > {
802
+ let value = self . get_mut ( class) ;
803
+ * value = value. checked_add ( weight) . ok_or ( ( ) ) ?;
804
+ Ok ( ( ) )
805
+ }
806
+
807
+ /// Subtract some weight of a specific dispatch class, saturating at the numeric bounds of
808
+ /// `Weight`.
809
+ pub fn sub ( & mut self , weight : Weight , class : DispatchClass ) {
810
+ let value = self . get_mut ( class) ;
811
+ * value = value. saturating_sub ( weight) ;
812
+ }
813
+ }
814
+
698
815
#[ cfg( test) ]
699
816
#[ allow( dead_code) ]
700
817
mod tests {
0 commit comments