Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions src/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,25 +573,29 @@ impl Decimal {
/// # Ok(())
/// # }
/// ```
pub fn from_scientific_exact(value: &str) -> Result<Decimal, Error> {
pub fn from_scientific_exact(value: &str) -> crate::Result<Decimal> {
const ERROR_MESSAGE: &str = "Failed to parse";

let mut split = value.splitn(2, ['e', 'E']);

let base = split.next().ok_or_else(|| Error::from(ERROR_MESSAGE))?;
let exp = split.next().ok_or_else(|| Error::from(ERROR_MESSAGE))?;
let base = split.next().ok_or(crate::Error::FailedToParseScientificFromString)?;
let exp = split.next().ok_or(crate::Error::FailedToParseScientificFromString)?;

let mut ret = Decimal::from_str(base)?;
let current_scale = ret.scale();

if let Some(stripped) = exp.strip_prefix('-') {
let exp: u32 = stripped.parse().map_err(|_| Error::from(ERROR_MESSAGE))?;
let exp: u32 = stripped
.parse()
.map_err(|_err| crate::Error::FailedToParseScientificFromString)?;
if exp > Self::MAX_SCALE {
return Err(Error::ScaleExceedsMaximumPrecision(exp));
}
ret.set_scale(current_scale + exp)?;
} else {
let exp: u32 = exp.parse().map_err(|_| Error::from(ERROR_MESSAGE))?;
let exp: u32 = exp
.parse()
.map_err(|_err| crate::Error::FailedToParseScientificFromString)?;
if exp <= current_scale {
ret.set_scale(current_scale - exp)?;
} else if exp > 0 {
Expand Down Expand Up @@ -1845,7 +1849,7 @@ macro_rules! impl_try_from_decimal {

#[inline]
fn try_from(t: Decimal) -> Result<Self, Error> {
$conversion_fn(&t).ok_or_else(|| Error::ConversionTo(stringify!($TInto).into()))
$conversion_fn(&t).ok_or_else(|| Error::ConversionTo(stringify!($TInto)))
}
}
};
Expand Down Expand Up @@ -1887,8 +1891,8 @@ macro_rules! impl_try_from_primitive {
};
}

impl_try_from_primitive!(f32, Self::from_f32, Error::ConversionTo("Decimal".into()));
impl_try_from_primitive!(f64, Self::from_f64, Error::ConversionTo("Decimal".into()));
impl_try_from_primitive!(f32, Self::from_f32, Error::ConversionTo("Decimal"));
impl_try_from_primitive!(f64, Self::from_f64, Error::ConversionTo("Decimal"));
impl_try_from_primitive!(&str, core::str::FromStr::from_str);

macro_rules! impl_from {
Expand Down
10 changes: 7 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ pub enum Error {
ErrorString(String),
/// The value provided exceeds `Decimal::MAX`.
ExceedsMaximumPossibleValue,
/// A string could not represent a scientific number.
FailedToParseScientificFromString,
/// The value provided is less than `Decimal::MIN`.
LessThanMinimumPossibleValue,
/// An underflow is when there are more fractional digits than can be represented within `Decimal`.
Expand All @@ -20,7 +22,7 @@ pub enum Error {
ScaleExceedsMaximumPrecision(u32),
/// Represents a failure to convert to/from `Decimal` to the specified type. This is typically
/// due to type constraints (e.g. `Decimal::MAX` cannot be converted into `i32`).
ConversionTo(String),
ConversionTo(&'static str),
}

impl<S> From<S> for Error
Expand All @@ -38,8 +40,7 @@ pub(crate) fn tail_error(from: &'static str) -> Result<Decimal, Error> {
Err(from.into())
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}
Comment on lines -41 to -42
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary anymore

impl core::error::Error for Error {}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -48,6 +49,9 @@ impl fmt::Display for Error {
Self::ExceedsMaximumPossibleValue => {
write!(f, "Number exceeds maximum value that can be represented.")
}
Self::FailedToParseScientificFromString => {
write!(f, "A string could not represent a scientific number.")
}
Self::LessThanMinimumPossibleValue => {
write!(f, "Number less than minimum value that can be represented.")
}
Expand Down
2 changes: 1 addition & 1 deletion src/postgres/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl<'a> FromSql<'a> for Decimal {
_ => "unknown special numeric",
};

return Err(Box::new(Error::ConversionTo(special.to_string())));
return Err(Box::new(Error::ConversionTo(special)));
}

// Number of digits (in base 10) to print after decimal separator
Expand Down
2 changes: 1 addition & 1 deletion tests/decimal_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3177,7 +3177,7 @@ fn it_converts_from_f64_retaining_bits() {
#[test]
fn it_converts_to_integers() {
assert_eq!(i64::try_from(Decimal::ONE), Ok(1));
assert_eq!(i64::try_from(Decimal::MAX), Err(Error::ConversionTo("i64".to_string())));
assert_eq!(i64::try_from(Decimal::MAX), Err(Error::ConversionTo("i64")));
assert_eq!(u128::try_from(Decimal::ONE_HUNDRED), Ok(100));
}

Expand Down