Improve `ParseAmountError::InputTooLarge`
This variant lacked pretty important information: what is the limit. We could just write it in the error message but it's even better to move it to a separate struct which also says how many characters exceed the limit - this helps users know how many need to be deleted.
This commit is contained in:
parent
b7689a7d60
commit
28d83551eb
|
@ -177,6 +177,10 @@ impl From<MissingDigitsError> for ParseError {
|
||||||
fn from(e: MissingDigitsError) -> Self { Self::Amount(e.into()) }
|
fn from(e: MissingDigitsError) -> Self { Self::Amount(e.into()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<InputTooLargeError> for ParseError {
|
||||||
|
fn from(e: InputTooLargeError) -> Self { Self::Amount(e.into()) }
|
||||||
|
}
|
||||||
|
|
||||||
impl From<InvalidCharacterError> for ParseError {
|
impl From<InvalidCharacterError> for ParseError {
|
||||||
fn from(e: InvalidCharacterError) -> Self { Self::Amount(e.into()) }
|
fn from(e: InvalidCharacterError) -> Self { Self::Amount(e.into()) }
|
||||||
}
|
}
|
||||||
|
@ -217,7 +221,7 @@ pub enum ParseAmountError {
|
||||||
/// A digit was expected but not found.
|
/// A digit was expected but not found.
|
||||||
MissingDigits(MissingDigitsError),
|
MissingDigits(MissingDigitsError),
|
||||||
/// Input string was too large.
|
/// Input string was too large.
|
||||||
InputTooLarge,
|
InputTooLarge(InputTooLargeError),
|
||||||
/// Invalid character in input.
|
/// Invalid character in input.
|
||||||
InvalidCharacter(InvalidCharacterError),
|
InvalidCharacter(InvalidCharacterError),
|
||||||
}
|
}
|
||||||
|
@ -228,6 +232,13 @@ impl From<MissingDigitsError> for ParseAmountError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<InputTooLargeError> for ParseAmountError {
|
||||||
|
fn from(value: InputTooLargeError) -> Self {
|
||||||
|
Self::InputTooLarge(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl From<InvalidCharacterError> for ParseAmountError {
|
impl From<InvalidCharacterError> for ParseAmountError {
|
||||||
fn from(value: InvalidCharacterError) -> Self {
|
fn from(value: InvalidCharacterError) -> Self {
|
||||||
Self::InvalidCharacter(value)
|
Self::InvalidCharacter(value)
|
||||||
|
@ -242,7 +253,7 @@ impl fmt::Display for ParseAmountError {
|
||||||
OutOfRange(ref error) => write_err!(f, "amount out of range"; error),
|
OutOfRange(ref error) => write_err!(f, "amount out of range"; error),
|
||||||
TooPrecise => f.write_str("amount has a too high precision"),
|
TooPrecise => f.write_str("amount has a too high precision"),
|
||||||
MissingDigits(ref error) => write_err!(f, "the input has too few digits"; error),
|
MissingDigits(ref error) => write_err!(f, "the input has too few digits"; error),
|
||||||
InputTooLarge => f.write_str("input string was too large"),
|
InputTooLarge(ref error) => write_err!(f, "the input is too large"; error),
|
||||||
InvalidCharacter(ref error) => write_err!(f, "invalid character in the input"; error),
|
InvalidCharacter(ref error) => write_err!(f, "invalid character in the input"; error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,7 +265,8 @@ impl std::error::Error for ParseAmountError {
|
||||||
use ParseAmountError::*;
|
use ParseAmountError::*;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
TooPrecise | InputTooLarge => None,
|
TooPrecise => None,
|
||||||
|
InputTooLarge(ref error) => Some(error),
|
||||||
OutOfRange(ref error) => Some(error),
|
OutOfRange(ref error) => Some(error),
|
||||||
MissingDigits(ref error) => Some(error),
|
MissingDigits(ref error) => Some(error),
|
||||||
InvalidCharacter(ref error) => Some(error),
|
InvalidCharacter(ref error) => Some(error),
|
||||||
|
@ -333,6 +345,24 @@ impl From<OutOfRangeError> for ParseAmountError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error returned when the input string is too large.
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub struct InputTooLargeError {
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for InputTooLargeError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self.len - INPUT_STRING_LEN_LIMIT {
|
||||||
|
1 => write!(f, "the input is one character longer than the maximum allowed length ({})", INPUT_STRING_LEN_LIMIT),
|
||||||
|
n => write!(f, "the input is {} characters longer than the maximum allowed length ({})", n, INPUT_STRING_LEN_LIMIT),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for InputTooLargeError {}
|
||||||
|
|
||||||
/// Error returned when digits were expected in the input but there were none.
|
/// Error returned when digits were expected in the input but there were none.
|
||||||
///
|
///
|
||||||
/// In particular, this is currently returned when the string is empty or only contains the minus sign.
|
/// In particular, this is currently returned when the string is empty or only contains the minus sign.
|
||||||
|
@ -457,6 +487,8 @@ fn is_too_precise(s: &str, precision: usize) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const INPUT_STRING_LEN_LIMIT: usize = 50;
|
||||||
|
|
||||||
/// Parse decimal string in the given denomination into a satoshi value and a
|
/// Parse decimal string in the given denomination into a satoshi value and a
|
||||||
/// bool indicator for a negative amount.
|
/// bool indicator for a negative amount.
|
||||||
fn parse_signed_to_satoshi(
|
fn parse_signed_to_satoshi(
|
||||||
|
@ -466,8 +498,8 @@ fn parse_signed_to_satoshi(
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
return Err(InnerParseError::MissingDigits(MissingDigitsError { kind: MissingDigitsKind::Empty }));
|
return Err(InnerParseError::MissingDigits(MissingDigitsError { kind: MissingDigitsKind::Empty }));
|
||||||
}
|
}
|
||||||
if s.len() > 50 {
|
if s.len() > INPUT_STRING_LEN_LIMIT {
|
||||||
return Err(InnerParseError::InputTooLarge);
|
return Err(InnerParseError::InputTooLarge(s.len()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_negative = s.starts_with('-');
|
let is_negative = s.starts_with('-');
|
||||||
|
@ -547,7 +579,7 @@ enum InnerParseError {
|
||||||
Overflow { is_negative: bool },
|
Overflow { is_negative: bool },
|
||||||
TooPrecise,
|
TooPrecise,
|
||||||
MissingDigits(MissingDigitsError),
|
MissingDigits(MissingDigitsError),
|
||||||
InputTooLarge,
|
InputTooLarge(usize),
|
||||||
InvalidCharacter(InvalidCharacterError),
|
InvalidCharacter(InvalidCharacterError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,7 +589,7 @@ impl InnerParseError {
|
||||||
Self::Overflow { is_negative } => OutOfRangeError { is_signed, is_greater_than_max: !is_negative }.into(),
|
Self::Overflow { is_negative } => OutOfRangeError { is_signed, is_greater_than_max: !is_negative }.into(),
|
||||||
Self::TooPrecise => ParseAmountError::TooPrecise,
|
Self::TooPrecise => ParseAmountError::TooPrecise,
|
||||||
Self::MissingDigits(error) => ParseAmountError::MissingDigits(error),
|
Self::MissingDigits(error) => ParseAmountError::MissingDigits(error),
|
||||||
Self::InputTooLarge => ParseAmountError::InputTooLarge,
|
Self::InputTooLarge(len) => ParseAmountError::InputTooLarge(InputTooLargeError { len }),
|
||||||
Self::InvalidCharacter(error) => ParseAmountError::InvalidCharacter(error),
|
Self::InvalidCharacter(error) => ParseAmountError::InvalidCharacter(error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2177,7 +2209,7 @@ mod tests {
|
||||||
// more than 50 chars.
|
// more than 50 chars.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
p("100000000000000.00000000000000000000000000000000000", Denomination::Bitcoin),
|
p("100000000000000.00000000000000000000000000000000000", Denomination::Bitcoin),
|
||||||
Err(E::InputTooLarge)
|
Err(E::InputTooLarge(InputTooLargeError { len: 51 }))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue