1 // Adapted from https://github.com/Alexhuszagh/rust-lexical.
2 
3 use super::algorithm::*;
4 use super::bhcomp::*;
5 use super::digit::*;
6 use super::exponent::*;
7 use 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.
parse_concise_float<F>(mantissa: u64, mant_exp: i32) -> F where F: Float,14 pub fn parse_concise_float<F>(mantissa: u64, mant_exp: i32) -> F
15 where
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.
parse_truncated_float<F>(integer: &[u8], mut fraction: &[u8], exponent: i32) -> F where F: Float,49 pub fn parse_truncated_float<F>(integer: &[u8], mut fraction: &[u8], exponent: i32) -> F
50 where
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 }
84