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.
This commit is contained in:
Jiri Jakes 2023-12-12 18:33:44 +08:00
parent 6fe073b324
commit daa47b2061
No known key found for this signature in database
GPG Key ID: 01F5B01A5D686F31
1 changed files with 9 additions and 7 deletions

View File

@ -938,14 +938,14 @@ impl SignedAmount {
/// Note: This only parses the value string. If you want to parse a value /// Note: This only parses the value string. If you want to parse a value
/// with denomination, use [FromStr]. /// with denomination, use [FromStr].
pub fn from_str_in(s: &str, denom: Denomination) -> Result<SignedAmount, ParseAmountError> { pub fn from_str_in(s: &str, denom: Denomination) -> Result<SignedAmount, ParseAmountError> {
let (negative, satoshi) = parse_signed_to_satoshi(s, denom)?; match parse_signed_to_satoshi(s, denom)? {
if satoshi > i64::MAX as u64 { // (negative, amount)
return Err(ParseAmountError::TooBig); (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 /// 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!(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("-.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("1.1", btc), Ok(Amount::from_sat(1_100_000_00)));
assert_eq!(p("100", sat), Ok(Amount::from_sat(100))); assert_eq!(p("100", sat), Ok(Amount::from_sat(100)));
assert_eq!(p("55", sat), Ok(Amount::from_sat(55))); assert_eq!(p("55", sat), Ok(Amount::from_sat(55)));
@ -2067,6 +2068,7 @@ mod tests {
scase("-5 satoshi", Ok(SignedAmount::from_sat(-5))); scase("-5 satoshi", Ok(SignedAmount::from_sat(-5)));
case("0.10000000 BTC", Ok(Amount::from_sat(100_000_00))); case("0.10000000 BTC", Ok(Amount::from_sat(100_000_00)));
scase("-100 bits", Ok(SignedAmount::from_sat(-10_000))); scase("-100 bits", Ok(SignedAmount::from_sat(-10_000)));
scase(&format!("{} SAT", i64::MIN), Ok(SignedAmount::from_sat(i64::MIN)));
} }
#[test] #[test]