Merge rust-bitcoin/rust-bitcoin#4389: Create impl_mul_assign and impl_div_assign macros

a92cc71f65 Create impl_mul_assign and impl_div_assign macros (Shing Him Ng)

Pull request description:

  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`

  Not as many types as I would have thought, but most of the operations result in a `NumOpResult`, which can't be then assigned back to the variable.

  Closes #4172

ACKs for top commit:
  apoelstra:
    ACK a92cc71f658771776557ea0a40d1d095d3b6d482; successfully ran local tests

Tree-SHA512: 30cfb077b9ba65af991eb17fa05ffc4a870c3f4ded746355d3a8577a71fe9a569588a882c2a936edcc9c88feede4d8bb1379a998e3f330894084a4e2fc434e6e
This commit is contained in:
merge-script 2025-04-25 14:08:00 +00:00
commit 12cef1d16b
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
3 changed files with 78 additions and 3 deletions

View File

@ -8,6 +8,7 @@ use NumOpResult as R;
use super::{Amount, SignedAmount}; use super::{Amount, SignedAmount};
use crate::{MathOp, NumOpError, NumOpResult, OptionExt}; use crate::{MathOp, NumOpError, NumOpResult, OptionExt};
use crate::internal_macros::{impl_mul_assign, impl_div_assign};
impl From<Amount> for NumOpResult<Amount> { impl From<Amount> for NumOpResult<Amount> {
fn from(a: Amount) -> Self { Self::Valid(a) } fn from(a: Amount) -> Self { Self::Valid(a) }
@ -230,6 +231,11 @@ crate::internal_macros::impl_op_for_references! {
} }
} }
impl_mul_assign!(NumOpResult<Amount>, u64);
impl_mul_assign!(NumOpResult<SignedAmount>, i64);
impl_div_assign!(NumOpResult<Amount>, u64);
impl_div_assign!(NumOpResult<SignedAmount>, i64);
impl ops::Neg for SignedAmount { impl ops::Neg for SignedAmount {
type Output = Self; type Output = Self;

View File

@ -23,6 +23,16 @@ fn sat(sat: u64) -> Amount { Amount::from_sat(sat).unwrap() }
#[track_caller] #[track_caller]
fn ssat(ssat: i64) -> SignedAmount { SignedAmount::from_sat(ssat).unwrap() } fn ssat(ssat: i64) -> SignedAmount { SignedAmount::from_sat(ssat).unwrap() }
#[track_caller]
fn res(n_sat: u64) -> NumOpResult<Amount>{
NumOpResult::from(sat(n_sat))
}
#[track_caller]
fn sres(n_sat: i64) -> NumOpResult<SignedAmount>{
NumOpResult::from(ssat(n_sat))
}
#[test] #[test]
fn sanity_check() { fn sanity_check() {
assert_eq!(ssat(-100).abs(), ssat(100)); assert_eq!(ssat(-100).abs(), ssat(100));
@ -1191,9 +1201,6 @@ fn signed_subtraction() {
#[test] #[test]
fn op_int_combos() { 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!(sat(23) * 31, res(713));
assert_eq!(ssat(23) * 31, sres(713)); assert_eq!(ssat(23) * 31, sres(713));
assert_eq!(res(23) * 31, res(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()); 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] #[test]
fn check_const() { fn check_const() {
assert_eq!(SignedAmount::ONE_BTC.to_sat(), 100_000_000); assert_eq!(SignedAmount::ONE_BTC.to_sat(), 100_000_000);

View File

@ -96,3 +96,31 @@ macro_rules! impl_sub_assign {
}; };
} }
pub(crate) use 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;