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.
This commit is contained in:
Tobin C. Harding 2024-11-01 17:15:06 +11:00
parent aa5c78430c
commit 3f2e760d1f
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
2 changed files with 14 additions and 17 deletions

View File

@ -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<ParseError> for ParseTimeError {
fn parser<T, E, S, F>(f: F) -> impl FnOnce(S) -> Result<T, E>
where
E: From<ParseError>,
S: AsRef<str> + Into<String>,
S: AsRef<str> + Into<InputString>,
F: FnOnce(u32) -> Result<T, ConversionError>,
{
move |s| {
@ -234,7 +234,7 @@ where
fn parse_hex<T, E, S, F>(s: S, f: F) -> Result<T, E>
where
E: From<ParseError>,
S: AsRef<str> + Into<String>,
S: AsRef<str> + Into<InputString>,
F: FnOnce(u32) -> Result<T, ConversionError>,
{
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: Into<String>>(s: S) -> impl FnOnce(core::num::ParseIntError) -> Self {
fn invalid_int<S: Into<InputString>>(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 <input_string> as absolute Height/Time (<subject> is above limit <upper_bound>)"
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 <input_string> as absolute Height/Time (<subject> is below limit <lower_bound>)"
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)

View File

@ -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<str>` which is not used later it's better to pass it as
/// owned since it avoids allocation in error case.
pub fn int<T: Integer, S: AsRef<str> + Into<String>>(s: S) -> Result<T, ParseIntError> {
pub fn int<T: Integer, S: AsRef<str> + Into<InputString>>(s: S) -> Result<T, ParseIntError> {
s.as_ref().parse().map_err(|error| {
ParseIntError {
input: s.into(),