From 86359fe364dc6044c0e5210d5a5aeee78ac688a2 Mon Sep 17 00:00:00 2001 From: yancy Date: Sat, 21 Sep 2024 09:21:42 -0500 Subject: [PATCH 1/6] Implement FeeRate addition --- units/src/fee_rate.rs | 45 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/units/src/fee_rate.rs b/units/src/fee_rate.rs index 626fd34d3..0eef2346e 100644 --- a/units/src/fee_rate.rs +++ b/units/src/fee_rate.rs @@ -3,7 +3,7 @@ //! Implements `FeeRate` and assoctiated features. use core::fmt; -use core::ops::{Div, Mul}; +use core::ops::{Add, Div, Mul}; #[cfg(feature = "arbitrary")] use arbitrary::{Arbitrary, Unstructured}; @@ -135,6 +135,36 @@ impl From for u64 { fn from(value: FeeRate) -> Self { value.to_sat_per_kwu() } } +impl Add for FeeRate { + type Output = FeeRate; + + fn add(self, rhs: FeeRate) -> Self::Output { FeeRate(self.0 + rhs.0) } +} + +impl Add for &FeeRate { + type Output = FeeRate; + + fn add(self, other: FeeRate) -> ::Output { + FeeRate(self.0 + other.0) + } +} + +impl Add<&FeeRate> for FeeRate { + type Output = FeeRate; + + fn add(self, other: &FeeRate) -> ::Output { + FeeRate(self.0 + other.0) + } +} + +impl<'a, 'b> Add<&'a FeeRate> for &'b FeeRate { + type Output = FeeRate; + + fn add(self, other: &'a FeeRate) -> ::Output { + FeeRate(self.0 + other.0) + } +} + /// Computes the ceiling so that the fee computation is conservative. impl Mul for Weight { type Output = Amount; @@ -162,6 +192,19 @@ crate::impl_parse_str_from_int_infallible!(FeeRate, u64, from_sat_per_kwu); mod tests { use super::*; + #[test] + #[allow(clippy::op_ref)] + fn addition() { + let one = FeeRate(1); + let two = FeeRate(2); + let three = FeeRate(3); + + assert!(one + two == three); + assert!(&one + two == three); + assert!(one + &two == three); + assert!(&one + &two == three); + } + #[test] fn fee_rate_const_test() { assert_eq!(0, FeeRate::ZERO.to_sat_per_kwu()); From 0e708700561c38f4c2b465917881801cb10eea46 Mon Sep 17 00:00:00 2001 From: yancy Date: Sat, 21 Sep 2024 09:23:57 -0500 Subject: [PATCH 2/6] Implement FeeRate subtraction --- units/src/fee_rate.rs | 45 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/units/src/fee_rate.rs b/units/src/fee_rate.rs index 0eef2346e..804cab2e5 100644 --- a/units/src/fee_rate.rs +++ b/units/src/fee_rate.rs @@ -3,7 +3,7 @@ //! Implements `FeeRate` and assoctiated features. use core::fmt; -use core::ops::{Add, Div, Mul}; +use core::ops::{Add, Sub, Div, Mul}; #[cfg(feature = "arbitrary")] use arbitrary::{Arbitrary, Unstructured}; @@ -165,6 +165,36 @@ impl<'a, 'b> Add<&'a FeeRate> for &'b FeeRate { } } +impl Sub for FeeRate { + type Output = FeeRate; + + fn sub(self, rhs: FeeRate) -> Self::Output { FeeRate(self.0 - rhs.0) } +} + +impl Sub for &FeeRate { + type Output = FeeRate; + + fn sub(self, other: FeeRate) -> ::Output { + FeeRate(self.0 - other.0) + } +} + +impl Sub<&FeeRate> for FeeRate { + type Output = FeeRate; + + fn sub(self, other: &FeeRate) -> ::Output { + FeeRate(self.0 - other.0) + } +} + +impl<'a, 'b> Sub<&'a FeeRate> for &'b FeeRate { + type Output = FeeRate; + + fn sub(self, other: &'a FeeRate) -> ::Output { + FeeRate(self.0 - other.0) + } +} + /// Computes the ceiling so that the fee computation is conservative. impl Mul for Weight { type Output = Amount; @@ -205,6 +235,19 @@ mod tests { assert!(&one + &two == three); } + #[test] + #[allow(clippy::op_ref)] + fn subtract() { + let one = FeeRate(1); + let two = FeeRate(2); + let three = FeeRate(3); + + assert!(three - two == one); + assert!(&three - two == one); + assert!(three - &two == one); + assert!(&three - &two == one); + } + #[test] fn fee_rate_const_test() { assert_eq!(0, FeeRate::ZERO.to_sat_per_kwu()); From c3a8bfa98dd3ead933dbb718525575ad248c6d0b Mon Sep 17 00:00:00 2001 From: yancy Date: Sat, 21 Sep 2024 09:26:37 -0500 Subject: [PATCH 3/6] Implement FeeRate AddAssign --- units/src/fee_rate.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/units/src/fee_rate.rs b/units/src/fee_rate.rs index 804cab2e5..595e5e6a3 100644 --- a/units/src/fee_rate.rs +++ b/units/src/fee_rate.rs @@ -3,7 +3,7 @@ //! Implements `FeeRate` and assoctiated features. use core::fmt; -use core::ops::{Add, Sub, Div, Mul}; +use core::ops::{Add, Sub, Div, Mul, AddAssign}; #[cfg(feature = "arbitrary")] use arbitrary::{Arbitrary, Unstructured}; @@ -216,6 +216,14 @@ impl Div for Amount { fn div(self, rhs: Weight) -> Self::Output { FeeRate(self.to_sat() * 1000 / rhs.to_wu()) } } +impl AddAssign for FeeRate { + fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0 } +} + +impl AddAssign<&FeeRate> for FeeRate { + fn add_assign(&mut self, rhs: &FeeRate) { self.0 += rhs.0 } +} + crate::impl_parse_str_from_int_infallible!(FeeRate, u64, from_sat_per_kwu); #[cfg(test)] @@ -248,6 +256,17 @@ mod tests { assert!(&three - &two == one); } + #[test] + fn add_assign() { + let mut f = FeeRate(1); + f += FeeRate(2); + assert_eq!(f, FeeRate(3)); + + let mut f = FeeRate(1); + f += &FeeRate(2); + assert_eq!(f, FeeRate(3)); + } + #[test] fn fee_rate_const_test() { assert_eq!(0, FeeRate::ZERO.to_sat_per_kwu()); From c967eabd43d3f1bf0b7cdd0c8828090397f1699d Mon Sep 17 00:00:00 2001 From: yancy Date: Sat, 21 Sep 2024 09:28:48 -0500 Subject: [PATCH 4/6] Implement FeeRate SubAssign --- units/src/fee_rate.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/units/src/fee_rate.rs b/units/src/fee_rate.rs index 595e5e6a3..8c89cea64 100644 --- a/units/src/fee_rate.rs +++ b/units/src/fee_rate.rs @@ -3,7 +3,7 @@ //! Implements `FeeRate` and assoctiated features. use core::fmt; -use core::ops::{Add, Sub, Div, Mul, AddAssign}; +use core::ops::{Add, Sub, Div, Mul, AddAssign, SubAssign}; #[cfg(feature = "arbitrary")] use arbitrary::{Arbitrary, Unstructured}; @@ -224,6 +224,14 @@ impl AddAssign<&FeeRate> for FeeRate { fn add_assign(&mut self, rhs: &FeeRate) { self.0 += rhs.0 } } +impl SubAssign for FeeRate { + fn sub_assign(&mut self, rhs: Self) { self.0 -= rhs.0 } +} + +impl SubAssign<&FeeRate> for FeeRate { + fn sub_assign(&mut self, rhs: &FeeRate) { self.0 -= rhs.0 } +} + crate::impl_parse_str_from_int_infallible!(FeeRate, u64, from_sat_per_kwu); #[cfg(test)] @@ -267,6 +275,17 @@ mod tests { assert_eq!(f, FeeRate(3)); } + #[test] + fn sub_assign() { + let mut f = FeeRate(3); + f -= FeeRate(2); + assert_eq!(f, FeeRate(1)); + + let mut f = FeeRate(3); + f -= &FeeRate(2); + assert_eq!(f, FeeRate(1)); + } + #[test] fn fee_rate_const_test() { assert_eq!(0, FeeRate::ZERO.to_sat_per_kwu()); From 212a7519299cf25fae24c329b50cbb98297e4e6a Mon Sep 17 00:00:00 2001 From: yancy Date: Sat, 21 Sep 2024 09:30:29 -0500 Subject: [PATCH 5/6] Implement FeeRate checked_add --- units/src/fee_rate.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/units/src/fee_rate.rs b/units/src/fee_rate.rs index 8c89cea64..9d8d7ee2a 100644 --- a/units/src/fee_rate.rs +++ b/units/src/fee_rate.rs @@ -96,6 +96,11 @@ impl FeeRate { Some(Amount::from_sat(sats)) } + /// Checked addition. + /// + /// Computes `self + rhs` returning [`None`] if overflow occured. + pub fn checked_add(self, rhs: u64) -> Option { self.0.checked_add(rhs).map(Self) } + /// Calculates the fee by multiplying this fee rate by weight, in weight units, returning [`None`] /// if an overflow occurred. /// @@ -286,6 +291,15 @@ mod tests { assert_eq!(f, FeeRate(1)); } + #[test] + fn checked_add() { + let f = FeeRate(1).checked_add(2).unwrap(); + assert_eq!(FeeRate(3), f); + + let f = FeeRate(u64::MAX).checked_add(1); + assert!(f.is_none()); + } + #[test] fn fee_rate_const_test() { assert_eq!(0, FeeRate::ZERO.to_sat_per_kwu()); From cb2146d5fac37ea7f68caa7cb92a0e44e1bb4c41 Mon Sep 17 00:00:00 2001 From: yancy Date: Sat, 21 Sep 2024 09:33:58 -0500 Subject: [PATCH 6/6] Implement FeeRate checked_sub --- units/src/fee_rate.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/units/src/fee_rate.rs b/units/src/fee_rate.rs index 9d8d7ee2a..7edc8cc17 100644 --- a/units/src/fee_rate.rs +++ b/units/src/fee_rate.rs @@ -101,6 +101,11 @@ impl FeeRate { /// Computes `self + rhs` returning [`None`] if overflow occured. pub fn checked_add(self, rhs: u64) -> Option { self.0.checked_add(rhs).map(Self) } + /// Checked subtraction. + /// + /// Computes `self - rhs` returning [`None`] if overflow occured. + pub fn checked_sub(self, rhs: u64) -> Option { self.0.checked_sub(rhs).map(Self) } + /// Calculates the fee by multiplying this fee rate by weight, in weight units, returning [`None`] /// if an overflow occurred. /// @@ -300,6 +305,15 @@ mod tests { assert!(f.is_none()); } + #[test] + fn checked_sub() { + let f = FeeRate(2).checked_sub(1).unwrap(); + assert_eq!(FeeRate(1), f); + + let f = FeeRate::ZERO.checked_sub(1); + assert!(f.is_none()); + } + #[test] fn fee_rate_const_test() { assert_eq!(0, FeeRate::ZERO.to_sat_per_kwu());