units: introduce impl_op_for_references and use it in three places
This macro can generally handle a lot of different cases where we implement "the same trait but on references". We introduce it here and use it in two places. We will use it in many more, but I wanted to make the diff small on this commit, which introduces the actual macro code and might take a bit of reading to understand. You may want to use --color-moved-ws=allow-indentation-change to review this, and the next commit. The next set of changes will mechanically delete other macros that are made redundant by this.
This commit is contained in:
parent
c90559de8e
commit
2da332e04a
|
@ -123,23 +123,23 @@ impl From<&SignedAmount> for NumOpResult<SignedAmount> {
|
|||
fn from(a: &SignedAmount) -> Self { Self::Valid(*a) }
|
||||
}
|
||||
|
||||
impl ops::Add for Amount {
|
||||
crate::internal_macros::impl_op_for_references! {
|
||||
impl ops::Add<Amount> for Amount {
|
||||
type Output = NumOpResult<Amount>;
|
||||
|
||||
fn add(self, rhs: Amount) -> Self::Output { self.checked_add(rhs).valid_or_error() }
|
||||
}
|
||||
}
|
||||
crate::internal_macros::impl_add_for_amount_references!(Amount);
|
||||
|
||||
impl ops::Add<NumOpResult<Amount>> for Amount {
|
||||
crate::internal_macros::impl_op_for_references! {
|
||||
impl ops::Add<NumOpResult<Amount>> for Amount {
|
||||
type Output = NumOpResult<Amount>;
|
||||
|
||||
fn add(self, rhs: NumOpResult<Amount>) -> Self::Output { rhs.and_then(|a| a + self) }
|
||||
}
|
||||
}
|
||||
impl ops::Add<NumOpResult<Amount>> for &Amount {
|
||||
type Output = NumOpResult<Amount>;
|
||||
|
||||
fn add(self, rhs: NumOpResult<Amount>) -> Self::Output { rhs.and_then(|a| a + self) }
|
||||
}
|
||||
// FIXME these two should be covered by generic impls below
|
||||
impl ops::Add<Amount> for NumOpResult<Amount> {
|
||||
type Output = NumOpResult<Amount>;
|
||||
|
||||
|
@ -151,12 +151,13 @@ impl ops::Add<&Amount> for NumOpResult<Amount> {
|
|||
fn add(self, rhs: &Amount) -> Self::Output { rhs + self }
|
||||
}
|
||||
|
||||
impl ops::Sub for Amount {
|
||||
crate::internal_macros::impl_op_for_references! {
|
||||
impl ops::Sub<Amount> for Amount {
|
||||
type Output = NumOpResult<Amount>;
|
||||
|
||||
fn sub(self, rhs: Amount) -> Self::Output { self.checked_sub(rhs).valid_or_error() }
|
||||
}
|
||||
}
|
||||
crate::internal_macros::impl_sub_for_amount_references!(Amount);
|
||||
|
||||
impl ops::Sub<NumOpResult<Amount>> for Amount {
|
||||
type Output = NumOpResult<Amount>;
|
||||
|
|
|
@ -4,6 +4,59 @@
|
|||
//!
|
||||
//! Macros meant to be used inside the `bitcoin-units` library.
|
||||
|
||||
/// Implements an opcode for various reference combinations.
|
||||
///
|
||||
/// Given `$ty`, assumes the `$op_trait<$other_ty>` trait is implemented on it,
|
||||
/// and implements the same trait with the full matrix of `&$ty` and `&$other_ty`:
|
||||
///
|
||||
/// - `Add<$other_ty> for &$ty`
|
||||
/// - `Add<&$other_ty> for $ty`
|
||||
/// - `Add<&$other_ty> for &$ty`
|
||||
///
|
||||
/// # Limitations
|
||||
///
|
||||
/// You must specify `$other_ty` and you may not use `Self`. So e.g. you need
|
||||
/// to write `impl ops::Add<Amount> for Amount { ... }` when calling this macro.
|
||||
macro_rules! impl_op_for_references {
|
||||
(
|
||||
impl $($op_trait:ident)::+<$other_ty:ty> for $ty:ty {
|
||||
type Output = $($main_output:ty)*;
|
||||
fn $op:ident($($main_args:tt)*) -> Self::Output {
|
||||
$($main_impl:tt)*
|
||||
}
|
||||
}
|
||||
) => {
|
||||
impl $($op_trait)::+<$other_ty> for $ty {
|
||||
type Output = $($main_output)*;
|
||||
fn $op($($main_args)*) -> Self::Output {
|
||||
$($main_impl)*
|
||||
}
|
||||
}
|
||||
|
||||
impl $($op_trait)::+<$other_ty> for &$ty {
|
||||
type Output = <$ty as $($op_trait)::+<$other_ty>>::Output;
|
||||
fn $op(self, rhs: $other_ty) -> Self::Output {
|
||||
(*self).$op(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl $($op_trait)::+<&$other_ty> for $ty {
|
||||
type Output = <$ty as $($op_trait)::+<$other_ty>>::Output;
|
||||
fn $op(self, rhs: &$other_ty) -> Self::Output {
|
||||
self.$op(*rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $($op_trait)::+<&'a $other_ty> for &$ty {
|
||||
type Output = <$ty as $($op_trait)::+<$other_ty>>::Output;
|
||||
fn $op(self, rhs: &$other_ty) -> Self::Output {
|
||||
(*self).$op(*rhs)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use impl_op_for_references;
|
||||
|
||||
/// Implements `ops::Add` for various references.
|
||||
///
|
||||
/// Requires `$ty` it implement `Add` e.g. 'impl Add<T> for T'. Adds impls of:
|
||||
|
|
Loading…
Reference in New Issue