Skip to content

Commit

Permalink
Merge rust-bitcoin#3677: units: Implement iter::Sum for all types t…
Browse files Browse the repository at this point in the history
…hat implement `ops::Add`

433f709 Implement iter::Sum for BlockInterval (Tobin C. Harding)
0369e64 Implement Sum for an iterator of references to amounts (Tobin C. Harding)
31f883a Implement iter::Sum for FeeRate (Tobin C. Harding)

Pull request description:

  Enables summing an iterator of values. Note that this does not include either `LockTime`s. `absolute::LockTime` should not be added and for `relative::LockTime` we have rust-bitcoin#3676

  Close: rust-bitcoin#1638

ACKs for top commit:
  apoelstra:
    ACK 433f709; successfully ran local tests; nice!
  sanket1729:
    utACK 433f709

Tree-SHA512: 1eda00f3bbbc61f795198ce8525a5a9b690478a8abc268da6d2e40de7d91decc28dd8211df0c6abeaf30148c7ec3907b85e3c5351972c354590569840e84d562
  • Loading branch information
apoelstra committed Nov 29, 2024
2 parents 7d8b9bd + 433f709 commit 85d1eb8
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 2 deletions.
10 changes: 10 additions & 0 deletions units/src/amount/signed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,16 @@ impl core::iter::Sum for SignedAmount {
}
}

impl<'a> core::iter::Sum<&'a SignedAmount> for SignedAmount {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a SignedAmount>,
{
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<Self> {
Expand Down
4 changes: 2 additions & 2 deletions units/src/amount/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,8 +825,8 @@ fn serde_as_sat_opt() {

#[test]
fn sum_amounts() {
assert_eq!(Amount::from_sat(0), [].into_iter().sum::<Amount>());
assert_eq!(SignedAmount::from_sat(0), [].into_iter().sum::<SignedAmount>());
assert_eq!(Amount::from_sat(0), [].iter().sum::<Amount>());
assert_eq!(SignedAmount::from_sat(0), [].iter().sum::<SignedAmount>());

let amounts = [Amount::from_sat(42), Amount::from_sat(1337), Amount::from_sat(21)];
let sum = amounts.into_iter().sum::<Amount>();
Expand Down
10 changes: 10 additions & 0 deletions units/src/amount/unsigned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,16 @@ impl core::iter::Sum for Amount {
}
}

impl<'a> core::iter::Sum<&'a Amount> for Amount {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Amount>,
{
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<Self> {
Expand Down
17 changes: 17 additions & 0 deletions units/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,23 @@ impl ops::SubAssign<BlockInterval> 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<I: Iterator<Item = Self>>(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<I>(iter: I) -> Self
where
I: Iterator<Item = &'a BlockInterval>,
{
let sum = iter.map(|interval| interval.0).sum();
BlockInterval::from_u32(sum)
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
18 changes: 18 additions & 0 deletions units/src/fee_rate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
FeeRate::from_sat_per_kwu(iter.map(FeeRate::to_sat_per_kwu).sum())
}
}

impl<'a> core::iter::Sum<&'a FeeRate> for FeeRate {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a FeeRate>,
{
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)]
Expand Down

0 comments on commit 85d1eb8

Please sign in to comment.