Replace invalidInteger with ParseIntError

We have a special type for wrapping integer parsing errors, use it.

To test this I added the following tests:

    #[test]
    pub fn debug_absolute_error_conversion_height() {
        let invalid_height = LOCK_TIME_THRESHOLD + 1;
        let _ = Height::from_consensus(invalid_height).unwrap();
    }

    #[test]
    pub fn debug_absolute_error_conversion_time() {
        let invalid_time =  LOCK_TIME_THRESHOLD - 1;
        let _ = Time::from_consensus(invalid_time).unwrap();
    }

    #[test]
    #[cfg(feature = "std")]
    pub fn debug_absolute_error_conversion_height_string() {
        let invalid_height = std::format!("{:x}", LOCK_TIME_THRESHOLD + 1);
        let _ = Height::from_hex(&invalid_height).unwrap();
    }

    #[test]
    #[cfg(feature = "std")]
    pub fn debug_absolute_error_conversion_time_string() {
        let invalid_time = std::format!("{:x}", LOCK_TIME_THRESHOLD - 1);
        let _ = Time::from_hex(&invalid_time).unwrap();
    }

    #[test]
    #[cfg(feature = "std")]
    pub fn debug_absolute_error_height_invalid_hex_string() {
        let _ = Height::from_hex("somerandomshit").unwrap();
    }

    #[test]
    #[cfg(feature = "std")]
    pub fn debug_absolute_error_time_invalid_hex_string() {
        let _ = Time::from_hex("somerandomshit").unwrap();
    }

Which resulted in the following output

Before:

---- locktime::absolute::tests::debug_absolute_error_conversion_height stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_height' panicked at units/src/locktime/absolute.rs:431:56:
called `Result::unwrap()` on an `Err` value: ConversionError { unit: Blocks, input: 500000001 }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- locktime::absolute::tests::debug_absolute_error_conversion_height_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_height_string' panicked at units/src/locktime/absolute.rs:444:51:
called `Result::unwrap()` on an `Err` value: ParseHeightError(Conversion(500000001))

---- locktime::absolute::tests::debug_absolute_error_conversion_time stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_time' panicked at units/src/locktime/absolute.rs:437:52:
called `Result::unwrap()` on an `Err` value: ConversionError { unit: Seconds, input: 499999999 }

---- locktime::absolute::tests::debug_absolute_error_height_invalid_hex_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_height_invalid_hex_string' panicked at units/src/locktime/absolute.rs:457:52:
called `Result::unwrap()` on an `Err` value: ParseHeightError(InvalidInteger { source: ParseIntError { kind: InvalidDigit }, input: "somerandomshit" })

---- locktime::absolute::tests::debug_absolute_error_conversion_time_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_time_string' panicked at units/src/locktime/absolute.rs:451:47:
called `Result::unwrap()` on an `Err` value: ParseTimeError(Conversion(499999999))

---- locktime::absolute::tests::debug_absolute_error_time_invalid_hex_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_time_invalid_hex_string' panicked at units/src/locktime/absolute.rs:464:50:
called `Result::unwrap()` on an `Err` value: ParseTimeError(InvalidInteger { source: ParseIntError { kind: InvalidDigit }, input: "somerandomshit" })

After:

---- locktime::absolute::tests::debug_absolute_error_conversion_height stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_height' panicked at units/src/locktime/absolute.rs:432:56:
called `Result::unwrap()` on an `Err` value: ConversionError { unit: Blocks, input: 500000001 }

---- locktime::absolute::tests::debug_absolute_error_conversion_height_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_height_string' panicked at units/src/locktime/absolute.rs:445:51:
called `Result::unwrap()` on an `Err` value: ParseHeightError(Conversion(500000001))

---- locktime::absolute::tests::debug_absolute_error_conversion_time stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_time' panicked at units/src/locktime/absolute.rs:438:52:
called `Result::unwrap()` on an `Err` value: ConversionError { unit: Seconds, input: 499999999 }

---- locktime::absolute::tests::debug_absolute_error_conversion_time_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_time_string' panicked at units/src/locktime/absolute.rs:452:47:
called `Result::unwrap()` on an `Err` value: ParseTimeError(Conversion(499999999))

---- locktime::absolute::tests::debug_absolute_error_height_invalid_hex_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_height_invalid_hex_string' panicked at units/src/locktime/absolute.rs:458:52:
called `Result::unwrap()` on an `Err` value: ParseHeightError(ParseInt(ParseIntError { input: "somerandomshit", bits: 32, is_signed: false, source: ParseIntError { kind: InvalidDigit } }))

---- locktime::absolute::tests::debug_absolute_error_time_invalid_hex_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_time_invalid_hex_string' panicked at units/src/locktime/absolute.rs:465:50:
called `Result::unwrap()` on an `Err` value: ParseTimeError(ParseInt(ParseIntError { input: "somerandomshit", bits: 32, is_signed: false, source: ParseIntError { kind: InvalidDigit } }))
This commit is contained in:
Tobin C. Harding 2024-11-01 16:54:45 +11:00
parent 9b7a706bfd
commit aa5c78430c
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
2 changed files with 11 additions and 10 deletions

View File

@ -8,6 +8,7 @@ use core::fmt;
use internals::write_err; use internals::write_err;
use crate::parse::ParseIntError;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use crate::parse; use crate::parse;
@ -300,7 +301,7 @@ impl fmt::Display for LockTimeUnit {
/// Internal - common representation for height and time. /// Internal - common representation for height and time.
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
enum ParseError { enum ParseError {
InvalidInteger { source: core::num::ParseIntError, input: String }, ParseInt(ParseIntError),
// unit implied by outer type // unit implied by outer type
// we use i64 to have nicer messages for negative values // we use i64 to have nicer messages for negative values
Conversion(i64), Conversion(i64),
@ -310,7 +311,7 @@ internals::impl_from_infallible!(ParseError);
impl ParseError { impl ParseError {
fn invalid_int<S: Into<String>>(s: S) -> impl FnOnce(core::num::ParseIntError) -> Self { fn invalid_int<S: Into<String>>(s: S) -> impl FnOnce(core::num::ParseIntError) -> Self {
move |source| Self::InvalidInteger { source, input: s.into() } move |source| Self::ParseInt(ParseIntError { input: s.into(), bits: 32, is_signed: true , source })
} }
fn display( fn display(
@ -325,13 +326,13 @@ impl ParseError {
use ParseError::*; use ParseError::*;
match self { match self {
InvalidInteger { source, input } if *source.kind() == IntErrorKind::PosOverflow => { ParseInt(ParseIntError { input, bits: _, is_signed: _, source }) if *source.kind() == IntErrorKind::PosOverflow => {
write!(f, "{} {} is above limit {}", subject, input, upper_bound) write!(f, "{} {} is above limit {}", subject, input, upper_bound)
} }
InvalidInteger { source, input } if *source.kind() == IntErrorKind::NegOverflow => { ParseInt(ParseIntError { input, bits: _, is_signed: _, source }) if *source.kind() == IntErrorKind::NegOverflow => {
write!(f, "{} {} is below limit {}", subject, input, lower_bound) write!(f, "{} {} is below limit {}", subject, input, lower_bound)
} }
InvalidInteger { source, input } => { ParseInt(ParseIntError { input, bits: _, is_signed: _, source }) => {
write_err!(f, "failed to parse {} as {}", input, subject; source) write_err!(f, "failed to parse {} as {}", input, subject; source)
} }
Conversion(value) if *value < i64::from(lower_bound) => { Conversion(value) if *value < i64::from(lower_bound) => {
@ -351,9 +352,9 @@ impl ParseError {
use ParseError::*; use ParseError::*;
match self { match self {
InvalidInteger { source, .. } if *source.kind() == IntErrorKind::PosOverflow => None, ParseInt(ParseIntError { source, .. }) if *source.kind() == IntErrorKind::PosOverflow => None,
InvalidInteger { source, .. } if *source.kind() == IntErrorKind::NegOverflow => None, ParseInt(ParseIntError { source, .. }) if *source.kind() == IntErrorKind::NegOverflow => None,
InvalidInteger { source, .. } => Some(source), ParseInt(ParseIntError { source, .. }) => Some(source),
Conversion(_) => None, Conversion(_) => None,
} }
} }

View File

@ -22,11 +22,11 @@ use internals::write_err;
pub struct ParseIntError { pub struct ParseIntError {
pub(crate) input: String, pub(crate) input: String,
// for displaying - see Display impl with nice error message below // for displaying - see Display impl with nice error message below
bits: u8, pub(crate) bits: u8,
// We could represent this as a single bit but it wouldn't actually derease the cost of moving // We could represent this as a single bit but it wouldn't actually derease the cost of moving
// the struct because String contains pointers so there will be padding of bits at least // the struct because String contains pointers so there will be padding of bits at least
// pointer_size - 1 bytes: min 1B in practice. // pointer_size - 1 bytes: min 1B in practice.
is_signed: bool, pub(crate) is_signed: bool,
pub(crate) source: core::num::ParseIntError, pub(crate) source: core::num::ParseIntError,
} }