From daa47b20614c4f5587365fdc2124c403c1b5948d Mon Sep 17 00:00:00 2001 From: Jiri Jakes Date: Tue, 12 Dec 2023 18:33:44 +0800 Subject: [PATCH] Allow `SignedAmount` parse values equal to i64::MIN Previously, parsing such textual value returned 'too big' error. This change fixes it and adds relevant tests. --- units/src/amount.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/units/src/amount.rs b/units/src/amount.rs index e61cfaa6..3f3e323e 100644 --- a/units/src/amount.rs +++ b/units/src/amount.rs @@ -938,14 +938,14 @@ impl SignedAmount { /// Note: This only parses the value string. If you want to parse a value /// with denomination, use [FromStr]. pub fn from_str_in(s: &str, denom: Denomination) -> Result { - let (negative, satoshi) = parse_signed_to_satoshi(s, denom)?; - if satoshi > i64::MAX as u64 { - return Err(ParseAmountError::TooBig); + match parse_signed_to_satoshi(s, denom)? { + // (negative, amount) + (false, sat) if sat > i64::MAX as u64 => Err(ParseAmountError::TooBig), + (false, sat) => Ok(SignedAmount(sat as i64)), + (true, sat) if sat == i64::MAX as u64 + 1 => Ok(SignedAmount(i64::MIN)), + (true, sat) if sat > i64::MAX as u64 + 1 => Err(ParseAmountError::TooBig), + (true, sat) => Ok(SignedAmount(-(sat as i64))), } - Ok(match negative { - true => SignedAmount(-(satoshi as i64)), - false => SignedAmount(satoshi as i64), - }) } /// Parses amounts with denomination suffix like they are produced with @@ -1762,6 +1762,7 @@ mod tests { assert_eq!(p("1", btc), Ok(Amount::from_sat(1_000_000_00))); assert_eq!(sp("-.5", btc), Ok(SignedAmount::from_sat(-500_000_00))); + assert_eq!(sp(&i64::MIN.to_string(), sat), Ok(SignedAmount::from_sat(i64::MIN))); assert_eq!(p("1.1", btc), Ok(Amount::from_sat(1_100_000_00))); assert_eq!(p("100", sat), Ok(Amount::from_sat(100))); assert_eq!(p("55", sat), Ok(Amount::from_sat(55))); @@ -2067,6 +2068,7 @@ mod tests { scase("-5 satoshi", Ok(SignedAmount::from_sat(-5))); case("0.10000000 BTC", Ok(Amount::from_sat(100_000_00))); scase("-100 bits", Ok(SignedAmount::from_sat(-10_000))); + scase(&format!("{} SAT", i64::MIN), Ok(SignedAmount::from_sat(i64::MIN))); } #[test]