Add generic Sub/AddAssign impl over NumOpResult
What changed, and why it matters
This commit adds convenience Rust traits (+= and -= operators) for a wrapper type called NumOpResult. It does not fix a bug or change existing behavior; it only makes it easier to add or subtract values that are already wrapped in a NumOpResult. There is no security relevance in the change itself.
No security action needed. Review as a normal API addition.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch adds generic AddAssign and SubAssign implementations for NumOpResult
Changed components
units/src/result.rsunits/src/fee_rate/mod.rsInspect captured patch +72 / −0
diff --git a/api/units/all-features.txt b/api/units/all-features.txt
index 07889bdf..cd908025 100644
--- a/api/units/all-features.txt
+++ b/api/units/all-features.txt
@@ -1344,6 +1344,10 @@ impl<T: core::cmp::PartialEq> core::cmp::PartialEq for bitcoin_units::result::Nu
impl<T: core::fmt::Debug> bitcoin_units::result::NumOpResult<T>
impl<T: core::fmt::Debug> core::fmt::Debug for bitcoin_units::result::NumOpResult<T>
impl<T: core::marker::Copy> core::marker::Copy for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::AddAssign + core::marker::Copy> core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::AddAssign> core::ops::arith::AddAssign<T> for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::SubAssign + core::marker::Copy> core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::SubAssign> core::ops::arith::SubAssign<T> for bitcoin_units::result::NumOpResult<T>
impl<T> bitcoin_units::result::NumOpResult<T>
impl<T> core::marker::Freeze for bitcoin_units::result::NumOpResult<T> where T: core::marker::Freeze
impl<T> core::marker::Send for bitcoin_units::result::NumOpResult<T> where T: core::marker::Send
@@ -2355,6 +2359,8 @@ pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: &T) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: &bitcoin_units::result::NumOpResult<T>) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: Self) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: T) -> Self::Output
+pub fn bitcoin_units::result::NumOpResult<T>::add_assign(&mut self, rhs: Self)
+pub fn bitcoin_units::result::NumOpResult<T>::add_assign(&mut self, rhs: T)
pub fn bitcoin_units::result::NumOpResult<T>::and_then<F>(self, op: F) -> Self where F: core::ops::function::FnOnce(T) -> Self
pub fn bitcoin_units::result::NumOpResult<T>::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result<Self>
pub fn bitcoin_units::result::NumOpResult<T>::clone(&self) -> bitcoin_units::result::NumOpResult<T>
@@ -2370,6 +2376,8 @@ pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: &T) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: &bitcoin_units::result::NumOpResult<T>) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: Self) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: T) -> Self::Output
+pub fn bitcoin_units::result::NumOpResult<T>::sub_assign(&mut self, rhs: Self)
+pub fn bitcoin_units::result::NumOpResult<T>::sub_assign(&mut self, rhs: T)
pub fn bitcoin_units::result::NumOpResult<T>::unwrap(self) -> T
pub fn bitcoin_units::result::NumOpResult<T>::unwrap_err(self) -> bitcoin_units::result::NumOpError
pub fn bitcoin_units::result::NumOpResult<T>::unwrap_or(self, default: T) -> T
diff --git a/api/units/alloc-only.txt b/api/units/alloc-only.txt
index de665ac2..b6333f98 100644
--- a/api/units/alloc-only.txt
+++ b/api/units/alloc-only.txt
@@ -1105,6 +1105,10 @@ impl<T: core::cmp::PartialEq> core::cmp::PartialEq for bitcoin_units::result::Nu
impl<T: core::fmt::Debug> bitcoin_units::result::NumOpResult<T>
impl<T: core::fmt::Debug> core::fmt::Debug for bitcoin_units::result::NumOpResult<T>
impl<T: core::marker::Copy> core::marker::Copy for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::AddAssign + core::marker::Copy> core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::AddAssign> core::ops::arith::AddAssign<T> for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::SubAssign + core::marker::Copy> core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::SubAssign> core::ops::arith::SubAssign<T> for bitcoin_units::result::NumOpResult<T>
impl<T> bitcoin_units::result::NumOpResult<T>
impl<T> core::marker::Freeze for bitcoin_units::result::NumOpResult<T> where T: core::marker::Freeze
impl<T> core::marker::Send for bitcoin_units::result::NumOpResult<T> where T: core::marker::Send
@@ -1996,6 +2000,8 @@ pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: &T) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: &bitcoin_units::result::NumOpResult<T>) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: Self) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: T) -> Self::Output
+pub fn bitcoin_units::result::NumOpResult<T>::add_assign(&mut self, rhs: Self)
+pub fn bitcoin_units::result::NumOpResult<T>::add_assign(&mut self, rhs: T)
pub fn bitcoin_units::result::NumOpResult<T>::and_then<F>(self, op: F) -> Self where F: core::ops::function::FnOnce(T) -> Self
pub fn bitcoin_units::result::NumOpResult<T>::clone(&self) -> bitcoin_units::result::NumOpResult<T>
pub fn bitcoin_units::result::NumOpResult<T>::eq(&self, other: &bitcoin_units::result::NumOpResult<T>) -> bool
@@ -2010,6 +2016,8 @@ pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: &T) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: &bitcoin_units::result::NumOpResult<T>) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: Self) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: T) -> Self::Output
+pub fn bitcoin_units::result::NumOpResult<T>::sub_assign(&mut self, rhs: Self)
+pub fn bitcoin_units::result::NumOpResult<T>::sub_assign(&mut self, rhs: T)
pub fn bitcoin_units::result::NumOpResult<T>::unwrap(self) -> T
pub fn bitcoin_units::result::NumOpResult<T>::unwrap_err(self) -> bitcoin_units::result::NumOpError
pub fn bitcoin_units::result::NumOpResult<T>::unwrap_or(self, default: T) -> T
diff --git a/api/units/no-features.txt b/api/units/no-features.txt
index 369e5d91..4dbb5000 100644
--- a/api/units/no-features.txt
+++ b/api/units/no-features.txt
@@ -1081,6 +1081,10 @@ impl<T: core::cmp::PartialEq> core::cmp::PartialEq for bitcoin_units::result::Nu
impl<T: core::fmt::Debug> bitcoin_units::result::NumOpResult<T>
impl<T: core::fmt::Debug> core::fmt::Debug for bitcoin_units::result::NumOpResult<T>
impl<T: core::marker::Copy> core::marker::Copy for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::AddAssign + core::marker::Copy> core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::AddAssign> core::ops::arith::AddAssign<T> for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::SubAssign + core::marker::Copy> core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult<T>
+impl<T: core::ops::arith::SubAssign> core::ops::arith::SubAssign<T> for bitcoin_units::result::NumOpResult<T>
impl<T> bitcoin_units::result::NumOpResult<T>
impl<T> core::marker::Freeze for bitcoin_units::result::NumOpResult<T> where T: core::marker::Freeze
impl<T> core::marker::Send for bitcoin_units::result::NumOpResult<T> where T: core::marker::Send
@@ -1938,6 +1942,8 @@ pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: &T) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: &bitcoin_units::result::NumOpResult<T>) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: Self) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::add(self, rhs: T) -> Self::Output
+pub fn bitcoin_units::result::NumOpResult<T>::add_assign(&mut self, rhs: Self)
+pub fn bitcoin_units::result::NumOpResult<T>::add_assign(&mut self, rhs: T)
pub fn bitcoin_units::result::NumOpResult<T>::and_then<F>(self, op: F) -> Self where F: core::ops::function::FnOnce(T) -> Self
pub fn bitcoin_units::result::NumOpResult<T>::clone(&self) -> bitcoin_units::result::NumOpResult<T>
pub fn bitcoin_units::result::NumOpResult<T>::eq(&self, other: &bitcoin_units::result::NumOpResult<T>) -> bool
@@ -1952,6 +1958,8 @@ pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: &T) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: &bitcoin_units::result::NumOpResult<T>) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: Self) -> Self::Output
pub fn bitcoin_units::result::NumOpResult<T>::sub(self, rhs: T) -> Self::Output
+pub fn bitcoin_units::result::NumOpResult<T>::sub_assign(&mut self, rhs: Self)
+pub fn bitcoin_units::result::NumOpResult<T>::sub_assign(&mut self, rhs: T)
pub fn bitcoin_units::result::NumOpResult<T>::unwrap(self) -> T
pub fn bitcoin_units::result::NumOpResult<T>::unwrap_err(self) -> bitcoin_units::result::NumOpError
pub fn bitcoin_units::result::NumOpResult<T>::unwrap_or(self, default: T) -> T
diff --git a/units/src/fee_rate/mod.rs b/units/src/fee_rate/mod.rs
index e94e4973..670adb9b 100644
--- a/units/src/fee_rate/mod.rs
+++ b/units/src/fee_rate/mod.rs
@@ -323,6 +323,14 @@ mod tests {
let mut f = FeeRate::from_sat_per_kwu(1);
f += &FeeRate::from_sat_per_kwu(2);
assert_eq!(f, FeeRate::from_sat_per_kwu(3));
+
+ let mut f = NumOpResult::Valid(FeeRate::from_sat_per_kwu(1));
+ f += FeeRate::from_sat_per_kwu(2);
+ assert_eq!(f, NumOpResult::Valid(FeeRate::from_sat_per_kwu(3)));
+
+ let mut f = NumOpResult::Valid(FeeRate::from_sat_per_kwu(1));
+ f += NumOpResult::Valid(FeeRate::from_sat_per_kwu(2));
+ assert_eq!(f, NumOpResult::Valid(FeeRate::from_sat_per_kwu(3)));
}
#[test]
@@ -334,6 +342,14 @@ mod tests {
let mut f = FeeRate::from_sat_per_kwu(3);
f -= &FeeRate::from_sat_per_kwu(2);
assert_eq!(f, FeeRate::from_sat_per_kwu(1));
+
+ let mut f = NumOpResult::Valid(FeeRate::from_sat_per_kwu(3));
+ f -= FeeRate::from_sat_per_kwu(2);
+ assert_eq!(f, NumOpResult::Valid(FeeRate::from_sat_per_kwu(1)));
+
+ let mut f = NumOpResult::Valid(FeeRate::from_sat_per_kwu(3));
+ f -= NumOpResult::Valid(FeeRate::from_sat_per_kwu(2));
+ assert_eq!(f, NumOpResult::Valid(FeeRate::from_sat_per_kwu(1)));
}
#[test]
diff --git a/units/src/result.rs b/units/src/result.rs
index 7b730d02..4d50dc82 100644
--- a/units/src/result.rs
+++ b/units/src/result.rs
@@ -269,6 +269,38 @@ crate::internal_macros::impl_op_for_references! {
}
}
+// Implement AddAssign on NumOpResults for all wrapped types that already implement AddAssign on themselves
+impl<T: ops::AddAssign> ops::AddAssign<T> for NumOpResult<T> {
+ fn add_assign(&mut self, rhs: T) {
+ if let Self::Valid(ref mut lhs) = self { *lhs += rhs }
+ }
+}
+
+impl<T: ops::AddAssign + Copy> ops::AddAssign<Self> for NumOpResult<T> {
+ fn add_assign(&mut self, rhs: Self) {
+ match (&self, rhs) {
+ (Self::Valid(_), Self::Valid(rhs)) => *self += rhs,
+ (_, _) => *self = Self::Error(NumOpError::while_doing(MathOp::Add)),
+ }
+ }
+}
+
+// Implement SubAssign on NumOpResults for all wrapped types that already implement SubAssign on themselves
+impl<T: ops::SubAssign> ops::SubAssign<T> for NumOpResult<T> {
+ fn sub_assign(&mut self, rhs: T) {
+ if let Self::Valid(ref mut lhs) = self { *lhs -= rhs }
+ }
+}
+
+impl<T: ops::SubAssign + Copy> ops::SubAssign<Self> for NumOpResult<T> {
+ fn sub_assign(&mut self, rhs: Self) {
+ match (&self, rhs) {
+ (Self::Valid(_), Self::Valid(rhs)) => *self -= rhs,
+ (_, _) => *self = Self::Error(NumOpError::while_doing(MathOp::Sub)),
+ }
+ }
+}
+
pub(crate) trait OptionExt<T> {
fn valid_or_error(self, op: MathOp) -> NumOpResult<T>;
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.