diff --git a/units/src/amount/result.rs b/units/src/amount/result.rs index a0ad26954..ccbc2150d 100644 --- a/units/src/amount/result.rs +++ b/units/src/amount/result.rs @@ -83,9 +83,11 @@ crate::internal_macros::impl_op_for_references! { fn div(self, rhs: u64) -> Self::Output { self.and_then(|lhs| lhs / rhs) } } impl ops::Div for Amount { - type Output = u64; + type Output = NumOpResult; - fn div(self, rhs: Amount) -> Self::Output { self.to_sat() / rhs.to_sat() } + fn div(self, rhs: Amount) -> Self::Output { + self.to_sat().checked_div(rhs.to_sat()).valid_or_error() + } } impl ops::Rem for Amount { @@ -158,9 +160,11 @@ crate::internal_macros::impl_op_for_references! { fn div(self, rhs: i64) -> Self::Output { self.and_then(|lhs| lhs / rhs) } } impl ops::Div for SignedAmount { - type Output = i64; + type Output = NumOpResult; - fn div(self, rhs: SignedAmount) -> Self::Output { self.to_sat() / rhs.to_sat() } + fn div(self, rhs: SignedAmount) -> Self::Output { + self.to_sat().checked_div(rhs.to_sat()).valid_or_error() + } } impl ops::Rem for SignedAmount { diff --git a/units/src/amount/tests.rs b/units/src/amount/tests.rs index 2dbefee14..a2a3bec07 100644 --- a/units/src/amount/tests.rs +++ b/units/src/amount/tests.rs @@ -1231,27 +1231,31 @@ fn op_int_combos() { #[test] fn unsigned_amount_div_by_amount() { - assert_eq!(sat(0) / sat(7), 0); - assert_eq!(sat(1897) / sat(7), 271); + assert_eq!((sat(0) / sat(7)).unwrap(), 0); + assert_eq!((sat(1897) / sat(7)).unwrap(), 271); } #[test] -#[should_panic(expected = "attempt to divide by zero")] -fn unsigned_amount_div_by_amount_zero() { let _ = sat(1897) / Amount::ZERO; } +fn unsigned_amount_div_by_amount_zero() { + let res = sat(1897) / Amount::ZERO; + assert!(res.into_result().is_err()); +} #[test] fn signed_amount_div_by_amount() { - assert_eq!(ssat(0) / ssat(7), 0); + assert_eq!((ssat(0) / ssat(7)).unwrap(), 0); - assert_eq!(ssat(1897) / ssat(7), 271); - assert_eq!(ssat(1897) / ssat(-7), -271); - assert_eq!(ssat(-1897) / ssat(7), -271); - assert_eq!(ssat(-1897) / ssat(-7), 271); + assert_eq!((ssat(1897) / ssat(7)).unwrap(), 271); + assert_eq!((ssat(1897) / ssat(-7)).unwrap(), -271); + assert_eq!((ssat(-1897) / ssat(7)).unwrap(), -271); + assert_eq!((ssat(-1897) / ssat(-7)).unwrap(), 271); } #[test] -#[should_panic(expected = "attempt to divide by zero")] -fn signed_amount_div_by_amount_zero() { let _ = ssat(1897) / SignedAmount::ZERO; } +fn signed_amount_div_by_amount_zero() { + let res = ssat(1897) / SignedAmount::ZERO; + assert!(res.into_result().is_err()); +} #[test] fn check_const() { diff --git a/units/src/fee.rs b/units/src/fee.rs index 5d277111e..e01f31571 100644 --- a/units/src/fee.rs +++ b/units/src/fee.rs @@ -178,18 +178,18 @@ crate::internal_macros::impl_op_for_references! { } impl ops::Div for Amount { - type Output = FeeRate; + type Output = NumOpResult; fn div(self, rhs: Weight) -> Self::Output { - FeeRate::from_sat_per_kwu(self.to_sat() * 1000 / rhs.to_wu()) + self.checked_div_by_weight_floor(rhs).valid_or_error() } } impl ops::Div for Amount { - type Output = Weight; + type Output = NumOpResult; fn div(self, rhs: FeeRate) -> Self::Output { - self.checked_div_by_fee_rate_floor(rhs).unwrap() + self.checked_div_by_fee_rate_floor(rhs).valid_or_error() } } } @@ -215,7 +215,7 @@ mod tests { #[test] fn fee_rate_div_by_weight() { - let fee_rate = Amount::from_sat_u32(329) / Weight::from_wu(381); + let fee_rate = (Amount::from_sat_u32(329) / Weight::from_wu(381)).unwrap(); assert_eq!(fee_rate, FeeRate::from_sat_per_kwu(863)); } @@ -275,21 +275,21 @@ mod tests { // Test exact division let amount = Amount::from_sat_u32(1000); let fee_rate = FeeRate::from_sat_per_kwu(2); - let weight = amount / fee_rate; + let weight = (amount / fee_rate).unwrap(); assert_eq!(weight, Weight::from_wu(500_000)); // Test reference division - let weight_ref = &amount / fee_rate; + let weight_ref = (&amount / fee_rate).unwrap(); assert_eq!(weight_ref, Weight::from_wu(500_000)); - let weight_ref2 = amount / &fee_rate; + let weight_ref2 = (amount / &fee_rate).unwrap(); assert_eq!(weight_ref2, Weight::from_wu(500_000)); - let weight_ref3 = &amount / &fee_rate; + let weight_ref3 = (&amount / &fee_rate).unwrap(); assert_eq!(weight_ref3, Weight::from_wu(500_000)); // Test truncation behavior let amount = Amount::from_sat_u32(1000); let fee_rate = FeeRate::from_sat_per_kwu(3); - let weight = amount / fee_rate; + let weight = (amount / fee_rate).unwrap(); // 1000 * 1000 = 1,000,000 msats // 1,000,000 / 3 = 333,333.33... wu // Should truncate down to 333,333 wu diff --git a/units/src/result.rs b/units/src/result.rs index 0663a6231..3cf626e40 100644 --- a/units/src/result.rs +++ b/units/src/result.rs @@ -6,7 +6,7 @@ use core::fmt; use NumOpResult as R; -use crate::{Amount, SignedAmount}; +use crate::{Amount, FeeRate, SignedAmount, Weight}; /// Result of a mathematical operation on two numeric types. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -125,7 +125,7 @@ macro_rules! impl_opt_ext { )* } } -impl_opt_ext!(Amount, SignedAmount); +impl_opt_ext!(Amount, SignedAmount, u64, i64, FeeRate, Weight); /// An error occurred while doing a mathematical operation. #[derive(Debug, Copy, Clone, PartialEq, Eq)]