serde_json/lexical/
parse.rs

1// Adapted from https://github.com/Alexhuszagh/rust-lexical.
2
3use super::algorithm::*;
4use super::bhcomp::*;
5use super::digit::*;
6use super::exponent::*;
7use super::num::*;
8
9// PARSERS
10// -------
11
12/// Parse float for which the entire integer and fraction parts fit into a 64
13/// bit mantissa.
14pub fn parse_concise_float<F>(mantissa: u64, mant_exp: i32) -> F
15where
16    F: Float,
17{
18    if let Some(float) = fast_path(mantissa, mant_exp) {
19        return float;
20    }
21
22    // Moderate path (use an extended 80-bit representation).
23    let truncated = false;
24    let (fp, valid) = moderate_path::<F>(mantissa, mant_exp, truncated);
25    if valid {
26        return fp.into_float::<F>();
27    }
28
29    let b = fp.into_downward_float::<F>();
30    if b.is_special() {
31        // We have a non-finite number, we get to leave early.
32        return b;
33    }
34
35    // Slow path, fast path didn't work.
36    let mut buffer = itoa::Buffer::new();
37    let integer = buffer.format(mantissa).as_bytes();
38    let fraction = &[];
39    bhcomp(b, integer, fraction, mant_exp)
40}
41
42/// Parse float from extracted float components.
43///
44/// * `integer`     - Slice containing the integer digits.
45/// * `fraction`    - Slice containing the fraction digits.
46/// * `exponent`    - Parsed, 32-bit exponent.
47///
48/// Precondition: The integer must not have leading zeros.
49pub fn parse_truncated_float<F>(integer: &[u8], mut fraction: &[u8], exponent: i32) -> F
50where
51    F: Float,
52{
53    // Trim trailing zeroes from the fraction part.
54    while fraction.last() == Some(&b'0') {
55        fraction = &fraction[..fraction.len() - 1];
56    }
57
58    // Calculate the number of truncated digits.
59    let mut truncated = 0;
60    let mut mantissa: u64 = 0;
61    let mut iter = integer.iter().chain(fraction);
62    for &c in &mut iter {
63        mantissa = match add_digit(mantissa, to_digit(c).unwrap()) {
64            Some(v) => v,
65            None => {
66                truncated = 1 + iter.count();
67                break;
68            }
69        };
70    }
71
72    let mant_exp = mantissa_exponent(exponent, fraction.len(), truncated);
73    let is_truncated = true;
74
75    fallback_path(
76        integer,
77        fraction,
78        mantissa,
79        exponent,
80        mant_exp,
81        is_truncated,
82    )
83}