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:
parent
aa5c78430c
commit
3f2e760d1f
|
@ -6,7 +6,7 @@
|
||||||
use alloc::{boxed::Box, string::String};
|
use alloc::{boxed::Box, string::String};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use internals::write_err;
|
use internals::error::InputString;
|
||||||
|
|
||||||
use crate::parse::ParseIntError;
|
use crate::parse::ParseIntError;
|
||||||
#[cfg(feature = "alloc")]
|
#[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>
|
fn parser<T, E, S, F>(f: F) -> impl FnOnce(S) -> Result<T, E>
|
||||||
where
|
where
|
||||||
E: From<ParseError>,
|
E: From<ParseError>,
|
||||||
S: AsRef<str> + Into<String>,
|
S: AsRef<str> + Into<InputString>,
|
||||||
F: FnOnce(u32) -> Result<T, ConversionError>,
|
F: FnOnce(u32) -> Result<T, ConversionError>,
|
||||||
{
|
{
|
||||||
move |s| {
|
move |s| {
|
||||||
|
@ -234,7 +234,7 @@ where
|
||||||
fn parse_hex<T, E, S, F>(s: S, f: F) -> Result<T, E>
|
fn parse_hex<T, E, S, F>(s: S, f: F) -> Result<T, E>
|
||||||
where
|
where
|
||||||
E: From<ParseError>,
|
E: From<ParseError>,
|
||||||
S: AsRef<str> + Into<String>,
|
S: AsRef<str> + Into<InputString>,
|
||||||
F: FnOnce(u32) -> Result<T, ConversionError>,
|
F: FnOnce(u32) -> Result<T, ConversionError>,
|
||||||
{
|
{
|
||||||
let n = i64::from_str_radix(parse::hex_remove_optional_prefix(s.as_ref()), 16)
|
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);
|
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<InputString>>(s: S) -> impl FnOnce(core::num::ParseIntError) -> Self {
|
||||||
move |source| Self::ParseInt(ParseIntError { input: s.into(), bits: 32, is_signed: true , source })
|
move |source| Self::ParseInt(ParseIntError { input: s.into(), bits: 32, is_signed: true , source })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,13 +327,15 @@ impl ParseError {
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
ParseInt(ParseIntError { input, bits: _, is_signed: _, source }) 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)
|
// 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 => {
|
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 }) => {
|
ParseInt(ParseIntError { input, bits: _, is_signed: _, source: _ }) => {
|
||||||
write_err!(f, "failed to parse {} as {}", input, subject; source)
|
write!(f, "{} ({})", input.display_cannot_parse("absolute Height/Time"), subject)
|
||||||
}
|
}
|
||||||
Conversion(value) if *value < i64::from(lower_bound) => {
|
Conversion(value) if *value < i64::from(lower_bound) => {
|
||||||
write!(f, "{} {} is below limit {}", subject, value, lower_bound)
|
write!(f, "{} {} is below limit {}", subject, value, lower_bound)
|
||||||
|
|
|
@ -7,6 +7,7 @@ use core::fmt;
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
|
||||||
use internals::write_err;
|
use internals::write_err;
|
||||||
|
use internals::error::InputString;
|
||||||
|
|
||||||
/// Error with rich context returned when a string can't be parsed as an integer.
|
/// 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)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct ParseIntError {
|
pub struct ParseIntError {
|
||||||
pub(crate) input: String,
|
pub(crate) input: InputString,
|
||||||
// for displaying - see Display impl with nice error message below
|
// for displaying - see Display impl with nice error message below
|
||||||
pub(crate) 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
|
||||||
|
@ -30,16 +31,10 @@ pub struct ParseIntError {
|
||||||
pub(crate) source: core::num::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 {
|
impl fmt::Display for ParseIntError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let signed = if self.is_signed { "signed" } else { "unsigned" };
|
let signed = if self.is_signed { "signed" } else { "unsigned" };
|
||||||
let n = if self.bits == 8 { "n" } else { "" };
|
write_err!(f, "{} ({}, {}-bit)", self.input.display_cannot_parse("integer"), signed, self.bits; self.source)
|
||||||
write_err!(f, "failed to parse '{}' as a{} {}-bit {} integer", self.input, n, self.bits, signed; 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
|
/// 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.
|
/// 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| {
|
s.as_ref().parse().map_err(|error| {
|
||||||
ParseIntError {
|
ParseIntError {
|
||||||
input: s.into(),
|
input: s.into(),
|
||||||
|
|
Loading…
Reference in New Issue