Implement CheckedSum for Weight iterator

Expose `checked_sum` method to sum an iterator of Weights checked.
This commit is contained in:
yancy 2025-05-23 14:58:03 -05:00
parent 0dbcd09bbc
commit 9dac4d69e0
3 changed files with 24 additions and 1 deletions

View File

@ -78,11 +78,12 @@ pub trait CheckedSum<R>: sealed::Sealed<R> {
} }
mod sealed { mod sealed {
use super::{Amount, SignedAmount}; use super::{Amount, SignedAmount, Weight};
/// Used to seal the `CheckedSum` trait /// Used to seal the `CheckedSum` trait
pub trait Sealed<A> {} pub trait Sealed<A> {}
impl<T> Sealed<Amount> for T where T: Iterator<Item = Amount> {} impl<T> Sealed<Amount> for T where T: Iterator<Item = Amount> {}
impl<T> Sealed<SignedAmount> for T where T: Iterator<Item = SignedAmount> {} impl<T> Sealed<SignedAmount> for T where T: Iterator<Item = SignedAmount> {}
impl<T> Sealed<Weight> for T where T: Iterator<Item = Weight> {}
} }

View File

@ -10,6 +10,8 @@ use arbitrary::{Arbitrary, Unstructured};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::CheckedSum;
/// The factor that non-witness serialization data is multiplied by during weight calculation. /// The factor that non-witness serialization data is multiplied by during weight calculation.
pub const WITNESS_SCALE_FACTOR: usize = 4; pub const WITNESS_SCALE_FACTOR: usize = 4;
@ -241,6 +243,13 @@ impl ops::RemAssign<u64> for Weight {
fn rem_assign(&mut self, rhs: u64) { *self = Weight::from_wu(self.to_wu() % rhs); } fn rem_assign(&mut self, rhs: u64) { *self = Weight::from_wu(self.to_wu() % rhs); }
} }
impl<T> CheckedSum<Weight> for T
where
T: Iterator<Item = Weight>,
{
fn checked_sum(mut self) -> Option<Weight> { self.try_fold(Weight::ZERO, Weight::checked_add) }
}
impl core::iter::Sum for Weight { impl core::iter::Sum for Weight {
fn sum<I>(iter: I) -> Self fn sum<I>(iter: I) -> Self
where where
@ -524,4 +533,16 @@ mod tests {
weight %= 3; weight %= 3;
assert_eq!(weight, Weight::from_wu(1)); assert_eq!(weight, Weight::from_wu(1));
} }
#[test]
#[cfg(feature = "alloc")]
fn checked_sum_weights() {
assert_eq!([].into_iter().checked_sum(), Some(Weight::ZERO));
let sum = alloc::vec![0, 1, 2].iter().map(|&w| Weight::from_wu(w)).checked_sum().unwrap();
assert_eq!(sum, Weight::from_wu(3));
let sum = alloc::vec![1, u64::MAX].iter().map(|&w| Weight::from_wu(w)).checked_sum();
assert!(sum.is_none());
}
} }

View File

@ -273,6 +273,7 @@ fn dyn_compatible() {
// If this builds then traits are dyn compatible. // If this builds then traits are dyn compatible.
struct Traits { struct Traits {
a: Box<dyn CheckedSum<Amount>>, a: Box<dyn CheckedSum<Amount>>,
b: Box<dyn CheckedSum<Weight>>,
// These traits are explicitly not dyn compatible. // These traits are explicitly not dyn compatible.
// b: Box<dyn amount::serde::SerdeAmount>, // b: Box<dyn amount::serde::SerdeAmount>,
// c: Box<dyn amount::serde::SerdeAmountForOpt>, // c: Box<dyn amount::serde::SerdeAmountForOpt>,