From a92cc71f658771776557ea0a40d1d095d3b6d482 Mon Sep 17 00:00:00 2001 From: Shing Him Ng Date: Tue, 22 Apr 2025 22:50:05 -0500 Subject: [PATCH] Create impl_mul_assign and impl_div_assign macros The macros were called on type-rhs pairs that have an existing implementation of ops::Mul and ops::Div, respectively, that have an `Output` of `Self` --- units/src/amount/result.rs | 6 +++++ units/src/amount/tests.rs | 47 +++++++++++++++++++++++++++++++++--- units/src/internal_macros.rs | 28 +++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/units/src/amount/result.rs b/units/src/amount/result.rs index 614e55bd8..e2c2ddcaf 100644 --- a/units/src/amount/result.rs +++ b/units/src/amount/result.rs @@ -8,6 +8,7 @@ use NumOpResult as R; use super::{Amount, SignedAmount}; use crate::{MathOp, NumOpError, NumOpResult, OptionExt}; +use crate::internal_macros::{impl_mul_assign, impl_div_assign}; impl From for NumOpResult { fn from(a: Amount) -> Self { Self::Valid(a) } @@ -230,6 +231,11 @@ crate::internal_macros::impl_op_for_references! { } } +impl_mul_assign!(NumOpResult, u64); +impl_mul_assign!(NumOpResult, i64); +impl_div_assign!(NumOpResult, u64); +impl_div_assign!(NumOpResult, i64); + impl ops::Neg for SignedAmount { type Output = Self; diff --git a/units/src/amount/tests.rs b/units/src/amount/tests.rs index d6752d450..5f240fb63 100644 --- a/units/src/amount/tests.rs +++ b/units/src/amount/tests.rs @@ -23,6 +23,16 @@ fn sat(sat: u64) -> Amount { Amount::from_sat(sat).unwrap() } #[track_caller] fn ssat(ssat: i64) -> SignedAmount { SignedAmount::from_sat(ssat).unwrap() } +#[track_caller] +fn res(n_sat: u64) -> NumOpResult{ + NumOpResult::from(sat(n_sat)) +} + +#[track_caller] +fn sres(n_sat: i64) -> NumOpResult{ + NumOpResult::from(ssat(n_sat)) +} + #[test] fn sanity_check() { assert_eq!(ssat(-100).abs(), ssat(100)); @@ -1191,9 +1201,6 @@ fn signed_subtraction() { #[test] fn op_int_combos() { - let res = |n_sat| NumOpResult::from(sat(n_sat)); - let sres = |n_ssat| NumOpResult::from(ssat(n_ssat)); - assert_eq!(sat(23) * 31, res(713)); assert_eq!(ssat(23) * 31, sres(713)); assert_eq!(res(23) * 31, res(713)); @@ -1257,6 +1264,40 @@ fn signed_amount_div_by_amount_zero() { assert!(res.into_result().is_err()); } +#[test] +fn mul_assign() { + let mut result = res(113); + result *= 367; + assert_eq!(result, res(41471)); + + let mut max = res(Amount::MAX.to_sat()); + max *= 2; + assert!(max.is_error()); + + let mut signed_result = sres(-211); + signed_result *= 431; + assert_eq!(signed_result, sres(-90941)); + + let mut min = sres(SignedAmount::MIN.to_sat()); + min *= 2; + assert!(min.is_error()); +} + +#[test] +fn div_assign() { + let mut result = res(41471); + result /= 367; + assert_eq!(result, res(113)); + result /= 0; + assert!(result.is_error()); + + let mut signed_result = sres(-90941); + signed_result /= 211; + assert_eq!(signed_result, sres(-431)); + signed_result /= 0; + assert!(signed_result.is_error()); +} + #[test] fn check_const() { assert_eq!(SignedAmount::ONE_BTC.to_sat(), 100_000_000); diff --git a/units/src/internal_macros.rs b/units/src/internal_macros.rs index ee6fc33d6..df8c56538 100644 --- a/units/src/internal_macros.rs +++ b/units/src/internal_macros.rs @@ -96,3 +96,31 @@ macro_rules! impl_sub_assign { }; } pub(crate) use impl_sub_assign; + +/// Implement `ops::MulAssign` for `$ty` multiplied by `$rhs` and `&$rhs`. +macro_rules! impl_mul_assign { + ($ty:ty, $rhs:ident) => { + impl core::ops::MulAssign<$rhs> for $ty { + fn mul_assign(&mut self, rhs: $rhs) { *self = *self * rhs } + } + + impl core::ops::MulAssign<&$rhs> for $ty { + fn mul_assign(&mut self, rhs: &$rhs) { *self = *self * *rhs } + } + }; +} +pub(crate) use impl_mul_assign; + +/// Implement `ops::DivAssign` for `$ty` divided by `$rhs` and `&$rhs`. +macro_rules! impl_div_assign { + ($ty:ty, $rhs:ident) => { + impl core::ops::DivAssign<$rhs> for $ty { + fn div_assign(&mut self, rhs: $rhs) { *self = *self / rhs } + } + + impl core::ops::DivAssign<&$rhs> for $ty { + fn div_assign(&mut self, rhs: &$rhs) { *self = *self / *rhs } + } + }; +} +pub(crate) use impl_div_assign;