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