From 3f2e760d1fef2951f93a2554cd53340b0d7a6e0b Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 1 Nov 2024 17:15:06 +1100 Subject: [PATCH] Replace String with InputString in ParseIntError Currently the `ParseIntError` contains an owned copy of the input string, this is causing us to have to use `alloc` everywhere. We already have a alloc-friendly string replacement type, the `InputString` - use it. --- units/src/locktime/absolute.rs | 18 ++++++++++-------- units/src/parse.rs | 13 ++++--------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/units/src/locktime/absolute.rs b/units/src/locktime/absolute.rs index 484439724..92283468d 100644 --- a/units/src/locktime/absolute.rs +++ b/units/src/locktime/absolute.rs @@ -6,7 +6,7 @@ use alloc::{boxed::Box, string::String}; use core::fmt; -use internals::write_err; +use internals::error::InputString; use crate::parse::ParseIntError; #[cfg(feature = "alloc")] @@ -221,7 +221,7 @@ impl From for ParseTimeError { fn parser(f: F) -> impl FnOnce(S) -> Result where E: From, - S: AsRef + Into, + S: AsRef + Into, F: FnOnce(u32) -> Result, { move |s| { @@ -234,7 +234,7 @@ where fn parse_hex(s: S, f: F) -> Result where E: From, - S: AsRef + Into, + S: AsRef + Into, F: FnOnce(u32) -> Result, { let n = i64::from_str_radix(parse::hex_remove_optional_prefix(s.as_ref()), 16) @@ -310,7 +310,7 @@ enum ParseError { internals::impl_from_infallible!(ParseError); impl ParseError { - fn invalid_int>(s: S) -> impl FnOnce(core::num::ParseIntError) -> Self { + fn invalid_int>(s: S) -> impl FnOnce(core::num::ParseIntError) -> Self { move |source| Self::ParseInt(ParseIntError { input: s.into(), bits: 32, is_signed: true , source }) } @@ -327,13 +327,15 @@ impl ParseError { match self { ParseInt(ParseIntError { input, bits: _, is_signed: _, source }) if *source.kind() == IntErrorKind::PosOverflow => { - write!(f, "{} {} is above limit {}", subject, input, upper_bound) + // Outputs "failed to parse as absolute Height/Time ( is above limit )" + write!(f, "{} ({} is above limit {})", input.display_cannot_parse("absolute Height/Time"), subject, upper_bound) } ParseInt(ParseIntError { input, bits: _, is_signed: _, source }) if *source.kind() == IntErrorKind::NegOverflow => { - write!(f, "{} {} is below limit {}", subject, input, lower_bound) + // Outputs "failed to parse as absolute Height/Time ( is below limit )" + write!(f, "{} ({} is below limit {})", input.display_cannot_parse("absolute Height/Time"), subject, lower_bound) } - ParseInt(ParseIntError { input, bits: _, is_signed: _, source }) => { - write_err!(f, "failed to parse {} as {}", input, subject; source) + ParseInt(ParseIntError { input, bits: _, is_signed: _, source: _ }) => { + write!(f, "{} ({})", input.display_cannot_parse("absolute Height/Time"), subject) } Conversion(value) if *value < i64::from(lower_bound) => { write!(f, "{} {} is below limit {}", subject, value, lower_bound) diff --git a/units/src/parse.rs b/units/src/parse.rs index 02df36f6a..a2ee0e4db 100644 --- a/units/src/parse.rs +++ b/units/src/parse.rs @@ -7,6 +7,7 @@ use core::fmt; use core::str::FromStr; use internals::write_err; +use internals::error::InputString; /// Error with rich context returned when a string can't be parsed as an integer. /// @@ -20,7 +21,7 @@ use internals::write_err; #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub struct ParseIntError { - pub(crate) input: String, + pub(crate) input: InputString, // for displaying - see Display impl with nice error message below pub(crate) bits: u8, // We could represent this as a single bit but it wouldn't actually derease the cost of moving @@ -30,16 +31,10 @@ pub struct ParseIntError { pub(crate) source: core::num::ParseIntError, } -impl ParseIntError { - /// Returns the input that was attempted to be parsed. - pub fn input(&self) -> &str { &self.input } -} - impl fmt::Display for ParseIntError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let signed = if self.is_signed { "signed" } else { "unsigned" }; - let n = if self.bits == 8 { "n" } else { "" }; - write_err!(f, "failed to parse '{}' as a{} {}-bit {} integer", self.input, n, self.bits, signed; self.source) + write_err!(f, "{} ({}, {}-bit)", self.input.display_cannot_parse("integer"), signed, self.bits; self.source) } } @@ -74,7 +69,7 @@ impl_integer!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128); /// /// If the caller owns `String` or `Box` which is not used later it's better to pass it as /// owned since it avoids allocation in error case. -pub fn int + Into>(s: S) -> Result { +pub fn int + Into>(s: S) -> Result { s.as_ref().parse().map_err(|error| { ParseIntError { input: s.into(),