From 31f883ac00e9d6887791fb41ac35d3e10b387d58 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 28 Nov 2024 15:49:01 +1100 Subject: [PATCH 1/3] Implement iter::Sum for FeeRate The `FeeRate` implements `ops::Add`, no reason not to enable summing an iterator of fee rates. --- units/src/fee_rate.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/units/src/fee_rate.rs b/units/src/fee_rate.rs index 4ed19f685b..c6f3f76fb1 100644 --- a/units/src/fee_rate.rs +++ b/units/src/fee_rate.rs @@ -267,6 +267,24 @@ impl SubAssign<&FeeRate> for FeeRate { fn sub_assign(&mut self, rhs: &FeeRate) { self.0 -= rhs.0 } } +impl core::iter::Sum for FeeRate { + fn sum(iter: I) -> Self + where + I: Iterator, + { + FeeRate::from_sat_per_kwu(iter.map(FeeRate::to_sat_per_kwu).sum()) + } +} + +impl<'a> core::iter::Sum<&'a FeeRate> for FeeRate { + fn sum(iter: I) -> Self + where + I: Iterator, + { + FeeRate::from_sat_per_kwu(iter.map(|f| FeeRate::to_sat_per_kwu(*f)).sum()) + } +} + crate::impl_parse_str_from_int_infallible!(FeeRate, u64, from_sat_per_kwu); #[cfg(test)] From 0369e64b56346f04aaaea60c159761651424f336 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 28 Nov 2024 15:51:29 +1100 Subject: [PATCH 2/3] Implement Sum for an iterator of references to amounts We have `iter::Sum` already for `Amount` and `SignedAmount`. Add an implementation for each to support iterators that yield references. --- units/src/amount/signed.rs | 10 ++++++++++ units/src/amount/tests.rs | 4 ++-- units/src/amount/unsigned.rs | 10 ++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/units/src/amount/signed.rs b/units/src/amount/signed.rs index b90fdd5e71..841b270714 100644 --- a/units/src/amount/signed.rs +++ b/units/src/amount/signed.rs @@ -442,6 +442,16 @@ impl core::iter::Sum for SignedAmount { } } +impl<'a> core::iter::Sum<&'a SignedAmount> for SignedAmount { + fn sum(iter: I) -> Self + where + I: Iterator, + { + let sats: i64 = iter.map(|amt| amt.0).sum(); + SignedAmount::from_sat(sats) + } +} + #[cfg(feature = "arbitrary")] impl<'a> Arbitrary<'a> for SignedAmount { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { diff --git a/units/src/amount/tests.rs b/units/src/amount/tests.rs index e695a443bd..00d54d7268 100644 --- a/units/src/amount/tests.rs +++ b/units/src/amount/tests.rs @@ -825,8 +825,8 @@ fn serde_as_sat_opt() { #[test] fn sum_amounts() { - assert_eq!(Amount::from_sat(0), [].into_iter().sum::()); - assert_eq!(SignedAmount::from_sat(0), [].into_iter().sum::()); + assert_eq!(Amount::from_sat(0), [].iter().sum::()); + assert_eq!(SignedAmount::from_sat(0), [].iter().sum::()); let amounts = [Amount::from_sat(42), Amount::from_sat(1337), Amount::from_sat(21)]; let sum = amounts.into_iter().sum::(); diff --git a/units/src/amount/unsigned.rs b/units/src/amount/unsigned.rs index a682623853..143c94e57f 100644 --- a/units/src/amount/unsigned.rs +++ b/units/src/amount/unsigned.rs @@ -432,6 +432,16 @@ impl core::iter::Sum for Amount { } } +impl<'a> core::iter::Sum<&'a Amount> for Amount { + fn sum(iter: I) -> Self + where + I: Iterator, + { + let sats: u64 = iter.map(|amt| amt.0).sum(); + Amount::from_sat(sats) + } +} + #[cfg(feature = "arbitrary")] impl<'a> Arbitrary<'a> for Amount { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { From 433f70939c3ecc10702ab6502e3f9bcd94dab739 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 28 Nov 2024 15:56:07 +1100 Subject: [PATCH 3/3] Implement iter::Sum for BlockInterval We support adding two intervals; no obvious reason not to support summing an iterator of intervals. --- units/src/block.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/units/src/block.rs b/units/src/block.rs index 7b407e33cf..aabb4c2ccb 100644 --- a/units/src/block.rs +++ b/units/src/block.rs @@ -231,6 +231,23 @@ impl ops::SubAssign for BlockInterval { fn sub_assign(&mut self, rhs: BlockInterval) { self.0 = self.to_u32() - rhs.to_u32(); } } +impl core::iter::Sum for BlockInterval { + fn sum>(iter: I) -> Self { + let sum = iter.map(|interval| interval.0).sum(); + BlockInterval::from_u32(sum) + } +} + +impl<'a> core::iter::Sum<&'a BlockInterval> for BlockInterval { + fn sum(iter: I) -> Self + where + I: Iterator, + { + let sum = iter.map(|interval| interval.0).sum(); + BlockInterval::from_u32(sum) + } +} + #[cfg(test)] mod tests { use super::*;