1/// Find and parse sign and get remaining bytes.
2#[inline]
3fn parse_sign<'a>(bytes: &'a [u8]) -> (bool, &'a [u8]) {
4    match bytes.get(0) {
5        Some(&b'+') => (true, &bytes[1..]),
6        Some(&b'-') => (false, &bytes[1..]),
7        _ => (true, bytes),
8    }
9}
10
11// Convert u8 to digit.
12#[inline]
13fn to_digit(c: u8) -> Option<u32> {
14    (c as char).to_digit(10)
15}
16
17// Add digit from exponent.
18#[inline]
19fn add_digit_i32(value: i32, digit: u32) -> Option<i32> {
20    return value.checked_mul(10)?.checked_add(digit as i32);
21}
22
23// Subtract digit from exponent.
24#[inline]
25fn sub_digit_i32(value: i32, digit: u32) -> Option<i32> {
26    return value.checked_mul(10)?.checked_sub(digit as i32);
27}
28
29// Convert character to digit.
30#[inline]
31fn is_digit(c: u8) -> bool {
32    to_digit(c).is_some()
33}
34
35// Split buffer at index.
36#[inline]
37fn split_at_index<'a>(digits: &'a [u8], index: usize) -> (&'a [u8], &'a [u8]) {
38    (&digits[..index], &digits[index..])
39}
40
41/// Consume until a an invalid digit is found.
42///
43/// - `digits`      - Slice containing 0 or more digits.
44#[inline]
45fn consume_digits<'a>(digits: &'a [u8]) -> (&'a [u8], &'a [u8]) {
46    // Consume all digits.
47    let mut index = 0;
48    while index < digits.len() && is_digit(digits[index]) {
49        index += 1;
50    }
51    split_at_index(digits, index)
52}
53
54// Trim leading 0s.
55#[inline]
56fn ltrim_zero<'a>(bytes: &'a [u8]) -> &'a [u8] {
57    let count = bytes.iter().take_while(|&&si| si == b'0').count();
58    &bytes[count..]
59}
60
61// Trim trailing 0s.
62#[inline]
63fn rtrim_zero<'a>(bytes: &'a [u8]) -> &'a [u8] {
64    let count = bytes.iter().rev().take_while(|&&si| si == b'0').count();
65    let index = bytes.len() - count;
66    &bytes[..index]
67}
68
69// PARSERS
70// -------
71
72/// Parse the exponent of the float.
73///
74/// * `exponent`    - Slice containing the exponent digits.
75/// * `is_positive` - If the exponent sign is positive.
76fn parse_exponent(exponent: &[u8], is_positive: bool) -> i32 {
77    // Parse the sign bit or current data.
78    let mut value: i32 = 0;
79    match is_positive {
80        true => {
81            for c in exponent {
82                value = match add_digit_i32(value, to_digit(*c).unwrap()) {
83                    Some(v) => v,
84                    None => return i32::max_value(),
85                };
86            }
87        },
88        false => {
89            for c in exponent {
90                value = match sub_digit_i32(value, to_digit(*c).unwrap()) {
91                    Some(v) => v,
92                    None => return i32::min_value(),
93                };
94            }
95        },
96    }
97
98    value
99}
100
101pub fn case_insensitive_starts_with<'a, 'b, Iter1, Iter2>(mut x: Iter1, mut y: Iter2) -> bool
102where
103    Iter1: Iterator<Item = &'a u8>,
104    Iter2: Iterator<Item = &'b u8>,
105{
106    // We use a faster optimization here for ASCII letters, which NaN
107    // and infinite strings **must** be. [A-Z] is 0x41-0x5A, while
108    // [a-z] is 0x61-0x7A. Therefore, the xor must be 0 or 32 if they
109    // are case-insensitive equal, but only if at least 1 of the inputs
110    // is an ASCII letter.
111    loop {
112        let yi = y.next();
113        if yi.is_none() {
114            return true;
115        }
116        let yi = *yi.unwrap();
117        let is_not_equal = x.next().map_or(true, |&xi| {
118            let xor = xi ^ yi;
119            xor != 0 && xor != 0x20
120        });
121        if is_not_equal {
122            return false;
123        }
124    }
125}
126
127/// Parse float from input bytes, returning the float and the remaining bytes.
128///
129/// * `bytes`    - Array of bytes leading with float-data.
130pub fn parse_float<'a, F>(bytes: &'a [u8]) -> (F, &'a [u8])
131where
132    F: minimal_lexical::Float,
133{
134    let start = bytes;
135
136    // Parse the sign.
137    let (is_positive, bytes) = parse_sign(bytes);
138
139    // Check NaN, Inf, Infinity
140    if case_insensitive_starts_with(bytes.iter(), b"NaN".iter()) {
141        let mut float = F::from_bits(F::EXPONENT_MASK | (F::HIDDEN_BIT_MASK >> 1));
142        if !is_positive {
143            float = -float;
144        }
145        return (float, &bytes[3..]);
146    } else if case_insensitive_starts_with(bytes.iter(), b"Infinity".iter()) {
147        let mut float = F::from_bits(F::EXPONENT_MASK);
148        if !is_positive {
149            float = -float;
150        }
151        return (float, &bytes[8..]);
152    } else if case_insensitive_starts_with(bytes.iter(), b"inf".iter()) {
153        let mut float = F::from_bits(F::EXPONENT_MASK);
154        if !is_positive {
155            float = -float;
156        }
157        return (float, &bytes[3..]);
158    }
159
160    // Extract and parse the float components:
161    //  1. Integer
162    //  2. Fraction
163    //  3. Exponent
164    let (integer_slc, bytes) = consume_digits(bytes);
165    let (fraction_slc, bytes) = match bytes.first() {
166        Some(&b'.') => consume_digits(&bytes[1..]),
167        _ => (&bytes[..0], bytes),
168    };
169    let (exponent, bytes) = match bytes.first() {
170        Some(&b'e') | Some(&b'E') => {
171            // Extract and parse the exponent.
172            let (is_positive, bytes) = parse_sign(&bytes[1..]);
173            let (exponent, bytes) = consume_digits(bytes);
174            (parse_exponent(exponent, is_positive), bytes)
175        },
176        _ => (0, bytes),
177    };
178
179    if bytes.len() == start.len() {
180        return (F::from_u64(0), bytes);
181    }
182
183    // Note: You may want to check and validate the float data here:
184    //  1). Many floats require integer or fraction digits, if a fraction
185    //      is present.
186    //  2). All floats require either integer or fraction digits.
187    //  3). Some floats do not allow a '+' sign before the significant digits.
188    //  4). Many floats require exponent digits after the exponent symbol.
189    //  5). Some floats do not allow a '+' sign before the exponent.
190
191    // We now need to trim leading and trailing 0s from the integer
192    // and fraction, respectively. This is required to make the
193    // fast and moderate paths more efficient, and for the slow
194    // path.
195    let integer_slc = ltrim_zero(integer_slc);
196    let fraction_slc = rtrim_zero(fraction_slc);
197
198    // Create the float and return our data.
199    let mut float: F =
200        minimal_lexical::parse_float(integer_slc.iter(), fraction_slc.iter(), exponent);
201    if !is_positive {
202        float = -float;
203    }
204
205    (float, bytes)
206}
207
208macro_rules! b {
209    ($x:literal) => {
210        $x.as_bytes()
211    };
212}
213
214#[test]
215fn f32_test() {
216    assert_eq!(
217        (184467440000000000000.0, b!("\x00\x00006")),
218        parse_float::<f32>(b"000184467440737095516150\x00\x00006")
219    );
220}
221
222#[test]
223fn f64_test() {
224    assert_eq!(
225        (184467440737095500000.0, b!("\x00\x00006")),
226        parse_float::<f64>(b"000184467440737095516150\x00\x00006")
227    );
228}
229