From 8bbec161150fe9c25c3725b0e3f63b18eac36534 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Mon, 17 Mar 2025 18:30:57 +0100 Subject: [PATCH] uucore: format: num_parser: Fold special value parsing in main parsing function --- .../src/lib/features/format/num_parser.rs | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/uucore/src/lib/features/format/num_parser.rs b/src/uucore/src/lib/features/format/num_parser.rs index 1296b52b3..67cb457ba 100644 --- a/src/uucore/src/lib/features/format/num_parser.rs +++ b/src/uucore/src/lib/features/format/num_parser.rs @@ -155,32 +155,39 @@ impl ParsedNumber { pub fn parse_f64(input: &str) -> Result> { match Self::parse(input, false) { Ok(v) => Ok(v.into_f64()), - Err(ParseError::NotNumeric) => Self::parse_f64_special_values(input), Err(e) => Err(e.map(|v, rest| ParseError::PartialMatch(v.into_f64(), rest))), } } - fn parse_f64_special_values(input: &str) -> Result> { - let (sign, rest) = if let Some(input) = input.strip_prefix('-') { - (-1.0, input) - } else { - (1.0, input) - }; - let prefix = rest + fn parse_special_value(input: &str, negative: bool) -> Result> { + let prefix = input .chars() .take(3) .map(|c| c.to_ascii_lowercase()) .collect::(); - let special = match prefix.as_str() { - "inf" => f64::INFINITY, - "nan" => f64::NAN, - _ => return Err(ParseError::NotNumeric), - } - .copysign(sign); - if rest.len() == 3 { + let special = Self { + number: match prefix.as_str() { + "inf" => { + if negative { + ExtendedBigDecimal::MinusInfinity + } else { + ExtendedBigDecimal::Infinity + } + } + "nan" => { + if negative { + ExtendedBigDecimal::MinusNan + } else { + ExtendedBigDecimal::Nan + } + } + _ => return Err(ParseError::NotNumeric), + }, + }; + if input.len() == 3 { Ok(special) } else { - Err(ParseError::PartialMatch(special, &rest[3..])) + Err(ParseError::PartialMatch(special, &input[3..])) } } @@ -251,9 +258,13 @@ impl ParsedNumber { } } - // If nothing has been parsed, declare the parsing unsuccessful + // If nothing has been parsed, check if this is a special value, or declare the parsing unsuccessful if let Some((0, _)) = chars.peek() { - return Err(ParseError::NotNumeric); + if integral_only { + return Err(ParseError::NotNumeric); + } else { + return Self::parse_special_value(unsigned, negative); + } } // TODO: Might be nice to implement a ExtendedBigDecimal copysign or negation function to move away some of this logic...