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