Skip to content

Commit

Permalink
fix: parse strings without a decimal point as well in from_str impl (
Browse files Browse the repository at this point in the history
  • Loading branch information
MathisWellmann authored Oct 21, 2024
1 parent 4015783 commit 47fe246
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 5 deletions.
25 changes: 20 additions & 5 deletions src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,22 @@ where
type Err = ParseDecimalError<I>;

fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.is_empty() {
return Err(ParseDecimalError::EmptyString);
}

// Strip the sign (-0 would parse to 0 and break our output).
let unsigned_s = s.strip_prefix('-').unwrap_or(s);

// Parse the unsigned representation.
let (integer_s, fractional_s) = unsigned_s
.split_once('.')
.ok_or(ParseDecimalError::MissingDecimalPoint)?;
let Some((integer_s, fractional_s)) = unsigned_s.split_once('.') else {
// The number does not contain a decimal point, but we can still try and parse
// it as an integer.
let integer = I::from_str(s)?;

return Decimal::try_from_scaled(integer, 0)
.ok_or(ParseDecimalError::Overflow(integer, I::ZERO));
};
let integer = I::from_str(integer_s)?;
let fractional = I::from_str(fractional_s)?;

Expand Down Expand Up @@ -86,6 +95,8 @@ pub enum ParseDecimalError<I>
where
I: Display,
{
#[error("Empty string provided")]
EmptyString,
#[error("Missing decimal point")]
MissingDecimalPoint,
#[error("Resultant decimal overflowed; integer={0}; fractional={1}")]
Expand Down Expand Up @@ -120,7 +131,7 @@ mod tests {

#[test]
fn uint64_9_from_str() {
assert_eq!("".parse::<Uint64_9>(), Err(ParseDecimalError::MissingDecimalPoint));
assert_eq!("".parse::<Uint64_9>(), Err(ParseDecimalError::EmptyString));
expect![[r#"
Err(
ParseInt(
Expand All @@ -132,6 +143,8 @@ mod tests {
"#]]
.assert_debug_eq(&"1.".parse::<Uint64_9>());
assert_eq!("1.0".parse::<Uint64_9>(), Ok(Uint64_9::ONE));
assert_eq!("10.0".parse::<Uint64_9>(), Ok(Uint64_9::try_from_scaled(10, 0).unwrap()));
assert_eq!("10".parse::<Uint64_9>(), Ok(Uint64_9::try_from_scaled(10, 0).unwrap()));
assert_eq!("0.1".parse::<Uint64_9>(), Ok(Decimal(10u64.pow(8))));
assert_eq!("0.123456789".parse::<Uint64_9>(), Ok(Decimal(123456789)));
assert_eq!("0.012345678".parse::<Uint64_9>(), Ok(Decimal(12345678)));
Expand Down Expand Up @@ -172,7 +185,7 @@ mod tests {

#[test]
fn int64_9_from_str() {
assert_eq!("".parse::<Int64_9>(), Err(ParseDecimalError::MissingDecimalPoint));
assert_eq!("".parse::<Int64_9>(), Err(ParseDecimalError::EmptyString));
expect![[r#"
Err(
ParseInt(
Expand All @@ -190,6 +203,8 @@ mod tests {
assert_eq!("0.000000001".parse::<Int64_9>(), Ok(Decimal(1)));
assert_eq!("0.0000000001".parse::<Int64_9>(), Err(ParseDecimalError::PrecisionLoss(10)));
assert_eq!("-1.0".parse::<Int64_9>(), Ok(-Int64_9::ONE));
assert_eq!("-10.0".parse::<Int64_9>(), Ok(Int64_9::try_from_scaled(-10, 0).unwrap()));
assert_eq!("-10".parse::<Int64_9>(), Ok(Int64_9::try_from_scaled(-10, 0).unwrap()));
assert_eq!("-0.1".parse::<Int64_9>(), Ok(-Decimal(10i64.pow(8))));
assert_eq!("-0.123456789".parse::<Int64_9>(), Ok(-Decimal(123456789)));
assert_eq!("-0.012345678".parse::<Int64_9>(), Ok(-Decimal(12345678)));
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ pub(crate) mod algorithms;

pub use aliases::*;
pub use decimal::*;
pub use display::ParseDecimalError;
pub use integer::*;

0 comments on commit 47fe246

Please sign in to comment.