diff --git a/units/src/amount.rs b/units/src/amount.rs index 87369d02..e5e29c2f 100644 --- a/units/src/amount.rs +++ b/units/src/amount.rs @@ -865,9 +865,9 @@ impl Amount { pub fn checked_rem(self, rhs: u64) -> Option { self.0.checked_rem(rhs).map(Amount) } /// Convert to a signed amount. - pub fn to_signed(self) -> Result { + pub fn to_signed(self) -> Result { if self.to_sat() > SignedAmount::MAX.to_sat() as u64 { - Err(ParseAmountError::OutOfRange(OutOfRangeError::too_big(true))) + Err(OutOfRangeError::too_big(true)) } else { Ok(SignedAmount::from_sat(self.to_sat() as i64)) } @@ -957,6 +957,14 @@ impl FromStr for Amount { fn from_str(s: &str) -> Result { Amount::from_str_with_denomination(s) } } +impl TryFrom for Amount { + type Error = OutOfRangeError; + + fn try_from(value: SignedAmount) -> Result { + value.to_unsigned() + } +} + impl core::iter::Sum for Amount { fn sum>(iter: I) -> Self { let sats: u64 = iter.map(|amt| amt.0).sum(); @@ -1340,6 +1348,14 @@ impl FromStr for SignedAmount { fn from_str(s: &str) -> Result { SignedAmount::from_str_with_denomination(s) } } +impl TryFrom for SignedAmount { + type Error = OutOfRangeError; + + fn try_from(value: Amount) -> Result { + value.to_signed() + } +} + impl core::iter::Sum for SignedAmount { fn sum>(iter: I) -> Self { let sats: i64 = iter.map(|amt| amt.0).sum(); @@ -1710,7 +1726,7 @@ mod verification { if n1 <= i64::MAX as u64 { Ok(SignedAmount::from_sat(n1.try_into().unwrap())) } else { - Err(ParseAmountError::OutOfRange(OutOfRangeError::too_big(true))) + Err(OutOfRangeError::too_big(true)) }, ); } @@ -1841,6 +1857,40 @@ mod tests { #[test] fn from_int_btc_panic() { Amount::from_int_btc(u64::MAX); } + #[test] + fn test_signed_amount_try_from_amount() { + let ua_positive = Amount::from_sat(123); + let sa_positive = SignedAmount::try_from(ua_positive).unwrap(); + assert_eq!(sa_positive, SignedAmount(123)); + + let ua_max = Amount::MAX; + let result = SignedAmount::try_from(ua_max); + assert_eq!( + result, + Err(OutOfRangeError { + is_signed: true, + is_greater_than_max: true + }) + ); + } + + #[test] + fn test_amount_try_from_signed_amount() { + let sa_positive = SignedAmount(123); + let ua_positive = Amount::try_from(sa_positive).unwrap(); + assert_eq!(ua_positive, Amount::from_sat(123)); + + let sa_negative = SignedAmount(-123); + let result = Amount::try_from(sa_negative); + assert_eq!( + result, + Err(OutOfRangeError { + is_signed: false, + is_greater_than_max: false + }) + ); + } + #[test] fn mul_div() { let sat = Amount::from_sat;