| 249 | } |
| 250 | |
| 251 | fn parse_float<Fl>(type_name: &'static str, s: &str) -> Result<Fl, ParseError> |
| 252 | where |
| 253 | Fl: NumFloat + FromStr, |
| 254 | { |
| 255 | // Matching PostgreSQL's float parsing behavior is tricky. PostgreSQL's |
| 256 | // implementation delegates almost entirely to strtof(3)/strtod(3), which |
| 257 | // will report an out-of-range error if a number was rounded to zero or |
| 258 | // infinity. For example, parsing "1e70" as a 32-bit float will yield an |
| 259 | // out-of-range error because it is rounded to infinity, but parsing an |
| 260 | // explicitly-specified "inf" will yield infinity without an error. |
| 261 | // |
| 262 | // To @benesch's knowledge, there is no Rust implementation of float parsing |
| 263 | // that reports whether underflow or overflow occurred. So we figure it out |
| 264 | // ourselves after the fact. If parsing the float returns infinity and the input |
| 265 | // was not an explicitly-specified infinity, then we know overflow occurred. |
| 266 | // If parsing the float returns zero and the input was not an explicitly-specified |
| 267 | // zero, then we know underflow occurred. |
| 268 | |
| 269 | // Matches `0`, `-0`, `+0`, `000000.00000`, `0.0e10`, 0., .0, et al. |
| 270 | static ZERO_RE: LazyLock<Regex> = |
| 271 | LazyLock::new(|| Regex::new(r#"(?i-u)^[-+]?(0+(\.0*)?|\.0+)(e|$)"#).unwrap()); |
| 272 | // Matches `inf`, `-inf`, `+inf`, `infinity`, et al. |
| 273 | static INF_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new("(?i-u)^[-+]?inf").unwrap()); |
| 274 | |
| 275 | let buf = s.trim(); |
| 276 | let f: Fl = buf |
| 277 | .parse() |
| 278 | .map_err(|_| ParseError::invalid_input_syntax(type_name, s))?; |
| 279 | match f.classify() { |
| 280 | FpCategory::Infinite if !INF_RE.is_match(buf.as_bytes()) => { |
| 281 | Err(ParseError::out_of_range(type_name, s)) |
| 282 | } |
| 283 | FpCategory::Zero if !ZERO_RE.is_match(buf.as_bytes()) => { |
| 284 | Err(ParseError::out_of_range(type_name, s)) |
| 285 | } |
| 286 | _ => Ok(f), |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | fn format_float<F, Fl>(buf: &mut F, f: Fl) -> Nestable |
| 291 | where |