lexical_parse_float/
parse.rs

1//! Shared trait and methods for parsing floats.
2//!
3//! This is adapted from [fast-float-rust](https://github.com/aldanor/fast-float-rust),
4//! a port of [fast_float](https://github.com/fastfloat/fast_float) to Rust.
5
6// NOTE: We never want to disable multi-digit optimizations when parsing our floats,
7// since the nanoseconds it saves on branching is irrelevant when considering decimal
8// points and fractional digits and it majorly improves longer floats.
9
10#![doc(hidden)]
11
12#[cfg(not(feature = "compact"))]
13use lexical_parse_integer::algorithm;
14#[cfg(feature = "f16")]
15use lexical_util::bf16::bf16;
16use lexical_util::digit::{char_to_digit_const, char_to_valid_digit_const};
17use lexical_util::error::Error;
18#[cfg(feature = "f16")]
19use lexical_util::f16::f16;
20use lexical_util::format::NumberFormat;
21use lexical_util::iterator::{AsBytes, Bytes, DigitsIter, Iter};
22use lexical_util::result::Result;
23use lexical_util::step::u64_step;
24
25#[cfg(any(feature = "compact", feature = "radix"))]
26use crate::bellerophon::bellerophon;
27#[cfg(feature = "power-of-two")]
28use crate::binary::{binary, slow_binary};
29use crate::float::{extended_to_float, ExtendedFloat80, LemireFloat};
30#[cfg(not(feature = "compact"))]
31use crate::lemire::lemire;
32use crate::number::Number;
33use crate::options::Options;
34use crate::shared;
35use crate::slow::slow_radix;
36
37// API
38// ---
39
40/// Check if the radix is a power-of-2.
41#[cfg(feature = "power-of-two")]
42macro_rules! is_power_two {
43    ($radix:expr) => {
44        matches!($radix, 2 | 4 | 8 | 16 | 32)
45    };
46}
47
48/// Check if the radix is valid and error otherwise
49#[cfg(feature = "power-of-two")]
50macro_rules! check_radix {
51    ($format:ident) => {{
52        let format = NumberFormat::<{ $format }> {};
53        if format.error() != Error::Success {
54            return Err(Error::InvalidRadix);
55        } else if format.radix() != format.exponent_base() {
56            let valid_radix = matches!(
57                (format.radix(), format.exponent_base()),
58                (4, 2) | (8, 2) | (16, 2) | (32, 2) | (16, 4)
59            );
60            if !valid_radix {
61                return Err(Error::InvalidRadix);
62            }
63        }
64    }};
65}
66
67/// Check if the decimal radix is valid and error otherwise.
68#[cfg(not(feature = "power-of-two"))]
69macro_rules! check_radix {
70    ($format:ident) => {{
71        let format = NumberFormat::<{ $format }> {};
72        if format.error() != Error::Success {
73            return Err(Error::InvalidRadix);
74        }
75    }};
76}
77
78/// Parse integer trait, implemented in terms of the optimized back-end.
79pub trait ParseFloat: LemireFloat {
80    /// Forward complete parser parameters to the backend.
81    #[cfg_attr(not(feature = "compact"), inline(always))]
82    fn parse_complete<const FORMAT: u128>(bytes: &[u8], options: &Options) -> Result<Self> {
83        check_radix!(FORMAT);
84        parse_complete::<Self, FORMAT>(bytes, options)
85    }
86
87    /// Forward partial parser parameters to the backend.
88    #[cfg_attr(not(feature = "compact"), inline(always))]
89    fn parse_partial<const FORMAT: u128>(bytes: &[u8], options: &Options) -> Result<(Self, usize)> {
90        check_radix!(FORMAT);
91        parse_partial::<Self, FORMAT>(bytes, options)
92    }
93
94    /// Forward complete parser parameters to the backend, using only the fast
95    /// path.
96    #[cfg_attr(not(feature = "compact"), inline(always))]
97    fn fast_path_complete<const FORMAT: u128>(bytes: &[u8], options: &Options) -> Result<Self> {
98        check_radix!(FORMAT);
99        fast_path_complete::<Self, FORMAT>(bytes, options)
100    }
101
102    /// Forward partial parser parameters to the backend, using only the fast
103    /// path.
104    #[cfg_attr(not(feature = "compact"), inline(always))]
105    fn fast_path_partial<const FORMAT: u128>(
106        bytes: &[u8],
107        options: &Options,
108    ) -> Result<(Self, usize)> {
109        check_radix!(FORMAT);
110        fast_path_partial::<Self, FORMAT>(bytes, options)
111    }
112}
113
114macro_rules! parse_float_impl {
115    ($($t:ty)*) => ($(
116        impl ParseFloat for $t {}
117    )*)
118}
119
120parse_float_impl! { f32 f64 }
121
122#[cfg(feature = "f16")]
123macro_rules! parse_float_as_f32 {
124    ($($t:ty)*) => ($(
125        impl ParseFloat for $t {
126            #[cfg_attr(not(feature = "compact"), inline(always))]
127            fn parse_complete<const FORMAT: u128>(bytes: &[u8], options: &Options)
128                -> Result<Self>
129            {
130                Ok(Self::from_f32(parse_complete::<f32, FORMAT>(bytes, options)?))
131            }
132
133            #[cfg_attr(not(feature = "compact"), inline(always))]
134            fn parse_partial<const FORMAT: u128>(bytes: &[u8], options: &Options)
135                -> Result<(Self, usize)>
136            {
137                let (float, count) = parse_partial::<f32, FORMAT>(bytes, options)?;
138                Ok((Self::from_f32(float), count))
139            }
140
141            #[cfg_attr(not(feature = "compact"), inline(always))]
142            fn fast_path_complete<const FORMAT: u128>(bytes: &[u8], options: &Options)
143                -> Result<Self>
144            {
145                Ok(Self::from_f32(fast_path_complete::<f32, FORMAT>(bytes, options)?))
146            }
147
148            #[cfg_attr(not(feature = "compact"), inline(always))]
149            fn fast_path_partial<const FORMAT: u128>(bytes: &[u8], options: &Options)
150                -> Result<(Self, usize)>
151            {
152                let (float, count) = fast_path_partial::<f32, FORMAT>(bytes, options)?;
153                Ok((Self::from_f32(float), count))
154            }
155        }
156    )*)
157}
158
159#[cfg(feature = "f16")]
160parse_float_as_f32! { bf16 f16 }
161
162// PARSE
163// -----
164
165// NOTE:
166//  The partial and complete parsers are done separately because it provides
167//  minor optimizations when parsing invalid input, and the logic is slightly
168//  different internally. Most of the code is shared, so the duplicated
169//  code is only like 30 lines.
170
171/// Parse the sign from the leading digits.
172#[cfg_attr(not(feature = "compact"), inline(always))]
173pub fn parse_mantissa_sign<const FORMAT: u128>(byte: &mut Bytes<'_, FORMAT>) -> Result<bool> {
174    let format = NumberFormat::<{ FORMAT }> {};
175    parse_sign!(
176        byte,
177        true,
178        format.no_positive_mantissa_sign(),
179        format.required_mantissa_sign(),
180        InvalidPositiveSign,
181        MissingSign
182    )
183}
184
185/// Parse the sign from the leading digits.
186#[cfg_attr(not(feature = "compact"), inline(always))]
187pub fn parse_exponent_sign<const FORMAT: u128>(byte: &mut Bytes<'_, FORMAT>) -> Result<bool> {
188    let format = NumberFormat::<{ FORMAT }> {};
189    parse_sign!(
190        byte,
191        true,
192        format.no_positive_exponent_sign(),
193        format.required_exponent_sign(),
194        InvalidPositiveExponentSign,
195        MissingExponentSign
196    )
197}
198
199/// Utility to extract the result and handle any errors from parsing a `Number`.
200///
201/// - `format` - The numerical format as a packed integer
202/// - `byte` - The `DigitsIter` iterator
203/// - `is_negative` - If the final value is negative
204/// - `parse_normal` - The function to parse non-special numbers with
205/// - `parse_special` - The function to parse special numbers with
206macro_rules! parse_number {
207    (
208        $format:ident,
209        $byte:ident,
210        $is_negative:ident,
211        $options:ident,
212        $parse_normal:ident,
213        $parse_special:ident
214    ) => {{
215        match $parse_normal::<$format>($byte.clone(), $is_negative, $options) {
216            Ok(n) => n,
217            Err(e) => {
218                if let Some(value) =
219                    $parse_special::<_, $format>($byte.clone(), $is_negative, $options)
220                {
221                    return Ok(value);
222                } else {
223                    return Err(e);
224                }
225            },
226        }
227    }};
228}
229
230/// Convert extended float to native.
231///
232/// - `type` - The native floating point type.
233/// - `fp` - The extended floating-point representation.
234macro_rules! to_native {
235    ($type:ident, $fp:ident, $is_negative:ident) => {{
236        let mut float = extended_to_float::<$type>($fp);
237        if $is_negative {
238            float = -float;
239        }
240        float
241    }};
242}
243
244/// Parse a float from bytes using a complete parser.
245#[inline(always)]
246#[allow(clippy::missing_inline_in_public_items)] // reason = "only public for testing"
247pub fn parse_complete<F: LemireFloat, const FORMAT: u128>(
248    bytes: &[u8],
249    options: &Options,
250) -> Result<F> {
251    let mut byte = bytes.bytes::<{ FORMAT }>();
252    let is_negative = parse_mantissa_sign(&mut byte)?;
253    if byte.integer_iter().is_consumed() {
254        if NumberFormat::<FORMAT>::REQUIRED_INTEGER_DIGITS
255            || NumberFormat::<FORMAT>::REQUIRED_MANTISSA_DIGITS
256        {
257            return Err(Error::Empty(byte.cursor()));
258        } else {
259            return Ok(F::ZERO);
260        }
261    }
262
263    // Parse our a small representation of our number.
264    let num: Number<'_> =
265        parse_number!(FORMAT, byte, is_negative, options, parse_complete_number, parse_special);
266    // Try the fast-path algorithm.
267    if let Some(value) = num.try_fast_path::<_, FORMAT>() {
268        return Ok(value);
269    }
270    // Now try the moderate path algorithm.
271    let mut fp = moderate_path::<F, FORMAT>(&num, options.lossy());
272
273    // Unable to correctly round the float using the fast or moderate algorithms.
274    // Fallback to a slower, but always correct algorithm. If we have
275    // lossy, we can't be here.
276    if fp.exp < 0 {
277        debug_assert!(!options.lossy(), "lossy algorithms never use slow algorithms");
278        // Undo the invalid extended float biasing.
279        fp.exp -= shared::INVALID_FP;
280        fp = slow_path::<F, FORMAT>(num, fp);
281    }
282
283    // Convert to native float and return result.
284    Ok(to_native!(F, fp, is_negative))
285}
286
287/// Parse a float using only the fast path as a complete parser.
288#[inline(always)]
289#[allow(clippy::missing_inline_in_public_items)] // reason = "only public for testing"
290pub fn fast_path_complete<F: LemireFloat, const FORMAT: u128>(
291    bytes: &[u8],
292    options: &Options,
293) -> Result<F> {
294    let mut byte = bytes.bytes::<{ FORMAT }>();
295    let is_negative = parse_mantissa_sign(&mut byte)?;
296    if byte.integer_iter().is_consumed() {
297        if NumberFormat::<FORMAT>::REQUIRED_INTEGER_DIGITS
298            || NumberFormat::<FORMAT>::REQUIRED_MANTISSA_DIGITS
299        {
300            return Err(Error::Empty(byte.cursor()));
301        } else {
302            return Ok(F::ZERO);
303        }
304    }
305
306    // Parse our a small representation of our number.
307    let num =
308        parse_number!(FORMAT, byte, is_negative, options, parse_complete_number, parse_special);
309    Ok(num.force_fast_path::<_, FORMAT>())
310}
311
312/// Parse a float from bytes using a partial parser.
313#[inline(always)]
314#[allow(clippy::missing_inline_in_public_items)] // reason = "only public for testing"
315pub fn parse_partial<F: LemireFloat, const FORMAT: u128>(
316    bytes: &[u8],
317    options: &Options,
318) -> Result<(F, usize)> {
319    let mut byte = bytes.bytes::<{ FORMAT }>();
320    let is_negative = parse_mantissa_sign(&mut byte)?;
321    if byte.integer_iter().is_consumed() {
322        if NumberFormat::<FORMAT>::REQUIRED_INTEGER_DIGITS
323            || NumberFormat::<FORMAT>::REQUIRED_MANTISSA_DIGITS
324        {
325            return Err(Error::Empty(byte.cursor()));
326        } else {
327            return Ok((F::ZERO, byte.cursor()));
328        }
329    }
330
331    // Parse our a small representation of our number.
332    let (num, count) = parse_number!(
333        FORMAT,
334        byte,
335        is_negative,
336        options,
337        parse_partial_number,
338        parse_partial_special
339    );
340    // Try the fast-path algorithm.
341    if let Some(value) = num.try_fast_path::<_, FORMAT>() {
342        return Ok((value, count));
343    }
344    // Now try the moderate path algorithm.
345    let mut fp = moderate_path::<F, FORMAT>(&num, options.lossy());
346
347    // Unable to correctly round the float using the fast or moderate algorithms.
348    // Fallback to a slower, but always correct algorithm. If we have
349    // lossy, we can't be here.
350    if fp.exp < 0 {
351        debug_assert!(!options.lossy(), "lossy algorithms never use slow algorithms");
352        // Undo the invalid extended float biasing.
353        fp.exp -= shared::INVALID_FP;
354        fp = slow_path::<F, FORMAT>(num, fp);
355    }
356
357    // Convert to native float and return result.
358    Ok((to_native!(F, fp, is_negative), count))
359}
360
361/// Parse a float using only the fast path as a partial parser.
362#[inline(always)]
363#[allow(clippy::missing_inline_in_public_items)] // reason = "only public for testing"
364pub fn fast_path_partial<F: LemireFloat, const FORMAT: u128>(
365    bytes: &[u8],
366    options: &Options,
367) -> Result<(F, usize)> {
368    let mut byte = bytes.bytes::<{ FORMAT }>();
369    let is_negative = parse_mantissa_sign(&mut byte)?;
370    if byte.integer_iter().is_consumed() {
371        if NumberFormat::<FORMAT>::REQUIRED_INTEGER_DIGITS
372            || NumberFormat::<FORMAT>::REQUIRED_MANTISSA_DIGITS
373        {
374            return Err(Error::Empty(byte.cursor()));
375        } else {
376            return Ok((F::ZERO, byte.cursor()));
377        }
378    }
379
380    // Parse our a small representation of our number.
381    let (num, count) = parse_number!(
382        FORMAT,
383        byte,
384        is_negative,
385        options,
386        parse_partial_number,
387        parse_partial_special
388    );
389    Ok((num.force_fast_path::<_, FORMAT>(), count))
390}
391
392// PATHS
393// -----
394
395/// Wrapper for different moderate-path algorithms.
396/// A return exponent of `-1` indicates an invalid value.
397#[must_use]
398#[inline(always)]
399pub fn moderate_path<F: LemireFloat, const FORMAT: u128>(
400    num: &Number,
401    lossy: bool,
402) -> ExtendedFloat80 {
403    #[cfg(feature = "compact")]
404    {
405        #[cfg(feature = "power-of-two")]
406        {
407            let format = NumberFormat::<{ FORMAT }> {};
408            if is_power_two!(format.mantissa_radix()) {
409                // Implement the power-of-two backends.
410                binary::<F, FORMAT>(num, lossy)
411            } else {
412                bellerophon::<F, FORMAT>(num, lossy)
413            }
414        }
415
416        #[cfg(not(feature = "power-of-two"))]
417        {
418            bellerophon::<F, FORMAT>(num, lossy)
419        }
420    }
421
422    #[cfg(not(feature = "compact"))]
423    {
424        #[cfg(feature = "radix")]
425        {
426            let format = NumberFormat::<{ FORMAT }> {};
427            let radix = format.mantissa_radix();
428            if radix == 10 {
429                lemire::<F>(num, lossy)
430            } else if is_power_two!(radix) {
431                // Implement the power-of-two backends.
432                binary::<F, FORMAT>(num, lossy)
433            } else {
434                bellerophon::<F, FORMAT>(num, lossy)
435            }
436        }
437
438        #[cfg(all(feature = "power-of-two", not(feature = "radix")))]
439        {
440            let format = NumberFormat::<{ FORMAT }> {};
441            let radix = format.mantissa_radix();
442            debug_assert!(matches!(radix, 2 | 4 | 8 | 10 | 16 | 32));
443            if radix == 10 {
444                lemire::<F>(num, lossy)
445            } else {
446                // Implement the power-of-two backends.
447                binary::<F, FORMAT>(num, lossy)
448            }
449        }
450
451        #[cfg(not(feature = "power-of-two"))]
452        {
453            lemire::<F>(num, lossy)
454        }
455    }
456}
457
458/// Invoke the slow path.
459/// At this point, the float string has already been validated.
460#[must_use]
461#[inline(always)]
462pub fn slow_path<F: LemireFloat, const FORMAT: u128>(
463    num: Number,
464    fp: ExtendedFloat80,
465) -> ExtendedFloat80 {
466    #[cfg(not(feature = "power-of-two"))]
467    {
468        slow_radix::<F, FORMAT>(num, fp)
469    }
470
471    #[cfg(feature = "power-of-two")]
472    {
473        let format = NumberFormat::<{ FORMAT }> {};
474        if is_power_two!(format.mantissa_radix()) {
475            slow_binary::<F, FORMAT>(num)
476        } else {
477            slow_radix::<F, FORMAT>(num, fp)
478        }
479    }
480}
481
482// NUMBER
483// ------
484
485/// Parse a partial, non-special floating point number.
486///
487/// This creates a representation of the float as the
488/// significant digits and the decimal exponent.
489#[cfg_attr(not(feature = "compact"), inline(always))]
490#[allow(unused_mut)] // reason = "used when format is enabled"
491#[allow(clippy::unwrap_used)] // reason = "developer error if we incorrectly assume an overflow"
492#[allow(clippy::collapsible_if)] // reason = "more readable uncollapsed"
493#[allow(clippy::cast_possible_wrap)] // reason = "no hardware supports buffers >= i64::MAX"
494#[allow(clippy::too_many_lines)] // reason = "function is one logical entity"
495pub fn parse_number<'a, const FORMAT: u128, const IS_PARTIAL: bool>(
496    mut byte: Bytes<'a, FORMAT>,
497    is_negative: bool,
498    options: &Options,
499) -> Result<(Number<'a>, usize)> {
500    //  NOTE:
501    //      There are no satisfactory optimizations to reduce the number
502    //      of multiplications for very long input strings, but this will
503    //      be a small fraction of the performance penalty anyway.
504    //
505    //      We've tried:
506    //          - checking for explicit overflow, via `overflowing_mul`.
507    //          - counting the max number of steps.
508    //          - subslicing the string, and only processing the first `step`
509    //            digits.
510    //          - pre-computing the maximum power, and only adding until then.
511    //
512    //      All of these lead to substantial performance penalty.
513    //      If we pre-parse the string, then only process it then, we
514    //      get a performance penalty of ~2.5x (20ns to 50ns) for common
515    //      floats, an unacceptable cost, while only improving performance
516    //      for rare floats 5-25% (9.3µs to 7.5µs for denormal with 6400
517    //      digits, and 7.8µs to 7.4µs for large floats with 6400 digits).
518    //
519    //      The performance cost is **almost** entirely in this function,
520    //      but additional branching **does** not improve performance,
521    //      and pre-tokenization is a recipe for failure. For halfway
522    //      cases with smaller numbers of digits, the majority of the
523    //      performance cost is in the big integer arithmetic (`pow` and
524    //      `parse_mantissa`), which suggests few optimizations can or should
525    //      be made.
526
527    // Config options
528    let format = NumberFormat::<{ FORMAT }> {};
529    let decimal_point = options.decimal_point();
530    let exponent_character = options.exponent();
531    debug_assert!(format.is_valid(), "should have already checked for an invalid number format");
532    debug_assert!(!byte.is_buffer_empty(), "should have previously checked for empty input");
533    let bits_per_digit = shared::log2(format.mantissa_radix()) as i64;
534    let bits_per_base = shared::log2(format.exponent_base()) as i64;
535
536    // INTEGER
537
538    // Check to see if we have a valid base prefix.
539    #[allow(unused_variables)]
540    let mut is_prefix = false;
541    #[cfg(feature = "format")]
542    {
543        let base_prefix = format.base_prefix();
544        let mut iter = byte.integer_iter();
545        if base_prefix != 0 && iter.read_if_value_cased(b'0').is_some() {
546            // Check to see if the next character is the base prefix.
547            // We must have a format like `0x`, `0d`, `0o`.
548            // NOTE: The check for empty integer digits happens below so
549            // we don't need a redundant check here.
550            is_prefix = true;
551            if iter.read_if_value(base_prefix, format.case_sensitive_base_prefix()).is_some()
552                && iter.is_buffer_empty()
553                && format.required_integer_digits()
554            {
555                return Err(Error::EmptyInteger(iter.cursor()));
556            }
557        }
558    }
559
560    // Parse our integral digits.
561    let mut mantissa = 0_u64;
562    let start = byte.clone();
563    #[cfg(not(feature = "compact"))]
564    parse_8digits::<_, FORMAT>(byte.integer_iter(), &mut mantissa);
565    parse_digits(byte.integer_iter(), format.mantissa_radix(), |digit| {
566        mantissa = mantissa.wrapping_mul(format.radix() as u64).wrapping_add(digit as u64);
567    });
568    let mut n_digits = byte.current_count() - start.current_count();
569    #[cfg(feature = "format")]
570    if format.required_integer_digits() && n_digits == 0 {
571        return Err(Error::EmptyInteger(byte.cursor()));
572    }
573
574    // Store the integer digits for slow-path algorithms.
575    // NOTE: We can't use the number of digits to extract the slice for
576    // non-contiguous iterators, but we also need to the number of digits
577    // for our value calculation. We store both, and let the compiler know
578    // to optimize it out when not needed.
579    let b_digits = if cfg!(feature = "format") && !byte.integer_iter().is_contiguous() {
580        byte.cursor() - start.cursor()
581    } else {
582        n_digits
583    };
584    debug_assert!(
585        b_digits <= start.as_slice().len(),
586        "number of digits parsed must <= buffer length"
587    );
588    // SAFETY: safe, since `n_digits <= start.as_slice().len()`.
589    // This is since `byte.len() >= start.len()` but has to have
590    // the same end bounds (that is, `start = byte.clone()`), so
591    // `0 <= byte.current_count() <= start.current_count() <= start.lent()`
592    // so, this will always return only the integer digits.
593    //
594    // NOTE: Removing this code leads to ~10% reduction in parsing
595    // that triggers the Eisell-Lemire algorithm or the digit comp
596    // algorithms, so don't remove the unsafe indexing.
597    let integer_digits = unsafe { start.as_slice().get_unchecked(..b_digits) };
598
599    // Check if integer leading zeros are disabled.
600    #[cfg(feature = "format")]
601    if !is_prefix && format.no_float_leading_zeros() {
602        if integer_digits.len() > 1 && integer_digits.first() == Some(&b'0') {
603            return Err(Error::InvalidLeadingZeros(start.cursor()));
604        }
605    }
606
607    // FRACTION
608
609    // Handle decimal point and digits afterwards.
610    let mut n_after_dot = 0;
611    let mut exponent = 0_i64;
612    let mut implicit_exponent: i64;
613    let int_end = n_digits as i64;
614    let mut fraction_digits = None;
615    let has_decimal = byte.first_is_cased(decimal_point);
616    if has_decimal {
617        // SAFETY: byte cannot be empty due to `first_is`
618        unsafe { byte.step_unchecked() };
619        let before = byte.clone();
620        #[cfg(not(feature = "compact"))]
621        parse_8digits::<_, FORMAT>(byte.fraction_iter(), &mut mantissa);
622        parse_digits(byte.fraction_iter(), format.mantissa_radix(), |digit| {
623            mantissa = mantissa.wrapping_mul(format.radix() as u64).wrapping_add(digit as u64);
624        });
625        n_after_dot = byte.current_count() - before.current_count();
626        // NOTE: We can't use the number of digits to extract the slice for
627        // non-contiguous iterators, but we also need to the number of digits
628        // for our value calculation. We store both, and let the compiler know
629        // to optimize it out when not needed.
630        let b_after_dot = if cfg!(feature = "format") && !byte.fraction_iter().is_contiguous() {
631            byte.cursor() - before.cursor()
632        } else {
633            n_after_dot
634        };
635
636        // Store the fraction digits for slow-path algorithms.
637        debug_assert!(
638            b_after_dot <= before.as_slice().len(),
639            "digits after dot must be smaller than buffer"
640        );
641        // SAFETY: safe, since `idx_after_dot <= before.as_slice().len()`.
642        fraction_digits = Some(unsafe { before.as_slice().get_unchecked(..b_after_dot) });
643
644        // Calculate the implicit exponent: the number of digits after the dot.
645        implicit_exponent = -(n_after_dot as i64);
646        if format.mantissa_radix() == format.exponent_base() {
647            exponent = implicit_exponent;
648        } else {
649            debug_assert!(bits_per_digit % bits_per_base == 0, "exponent must be a power of base");
650            exponent = implicit_exponent * bits_per_digit / bits_per_base;
651        };
652        #[cfg(feature = "format")]
653        if format.required_fraction_digits() && n_after_dot == 0 {
654            return Err(Error::EmptyFraction(byte.cursor()));
655        }
656    }
657
658    // NOTE: Check if we have our exponent **BEFORE** checking if the
659    // mantissa is empty, so we can ensure
660    let has_exponent = byte
661        .first_is(exponent_character, format.case_sensitive_exponent() && cfg!(feature = "format"));
662
663    // check to see if we have any invalid leading zeros
664    n_digits += n_after_dot;
665    if format.required_mantissa_digits()
666        && (n_digits == 0 || (cfg!(feature = "format") && byte.current_count() == 0))
667    {
668        let any_digits = start.clone().integer_iter().peek().is_some();
669        // NOTE: This is because numbers like `_12.34` have significant digits,
670        // they just don't have a valid digit (#97).
671        if has_decimal || has_exponent || !any_digits || IS_PARTIAL {
672            return Err(Error::EmptyMantissa(byte.cursor()));
673        } else {
674            return Err(Error::InvalidDigit(start.cursor()));
675        }
676    }
677
678    // EXPONENT
679
680    // Handle scientific notation.
681    let mut explicit_exponent = 0_i64;
682    if has_exponent {
683        // NOTE: See above for the safety invariant above `required_mantissa_digits`.
684        // This is separated for correctness concerns, and therefore the two cannot
685        // be on the same line.
686        // SAFETY: byte cannot be empty due to `first_is` from `has_exponent`.`
687        unsafe { byte.step_unchecked() };
688
689        // Check float format syntax checks.
690        #[cfg(feature = "format")]
691        {
692            // NOTE: We've overstepped for the safety invariant before.
693            if format.no_exponent_notation() {
694                return Err(Error::InvalidExponent(byte.cursor() - 1));
695            }
696            // Check if we have no fraction but we required exponent notation.
697            if format.no_exponent_without_fraction() && fraction_digits.is_none() {
698                return Err(Error::ExponentWithoutFraction(byte.cursor() - 1));
699            }
700        }
701
702        let is_negative_exponent = parse_exponent_sign(&mut byte)?;
703        let before = byte.current_count();
704        parse_digits(byte.exponent_iter(), format.exponent_radix(), |digit| {
705            if explicit_exponent < 0x10000000 {
706                explicit_exponent *= format.exponent_radix() as i64;
707                explicit_exponent += digit as i64;
708            }
709        });
710        if format.required_exponent_digits() && byte.current_count() - before == 0 {
711            return Err(Error::EmptyExponent(byte.cursor()));
712        }
713        // Handle our sign, and get the explicit part of the exponent.
714        explicit_exponent = if is_negative_exponent {
715            -explicit_exponent
716        } else {
717            explicit_exponent
718        };
719        exponent += explicit_exponent;
720    } else if cfg!(feature = "format") && format.required_exponent_notation() {
721        return Err(Error::MissingExponent(byte.cursor()));
722    }
723
724    // Check to see if we have a valid base suffix.
725    // We've already trimmed any leading digit separators here, so we can be safe
726    // that the first character **is not** a digit separator.
727    #[allow(unused_variables)]
728    let base_suffix = format.base_suffix();
729    #[cfg(feature = "format")]
730    if base_suffix != 0 {
731        if byte.first_is(base_suffix, format.case_sensitive_base_suffix()) {
732            // SAFETY: safe since `byte.len() >= 1`.
733            unsafe { byte.step_unchecked() };
734        }
735    }
736
737    // CHECK OVERFLOW
738
739    // Get the number of parsed digits (total), and redo if we had overflow.
740    let end = byte.cursor();
741    let mut step = u64_step(format.mantissa_radix());
742    let mut many_digits = false;
743    #[cfg(feature = "format")]
744    if !format.required_mantissa_digits() && n_digits == 0 {
745        exponent = 0;
746    }
747    if n_digits <= step {
748        return Ok((
749            Number {
750                exponent,
751                mantissa,
752                is_negative,
753                many_digits: false,
754                integer: integer_digits,
755                fraction: fraction_digits,
756            },
757            end,
758        ));
759    }
760
761    // Check for leading zeros, and to see if we had a false overflow.
762    n_digits -= step;
763    let mut zeros = start.clone();
764    let mut zeros_integer = zeros.integer_iter();
765    n_digits = n_digits.saturating_sub(zeros_integer.skip_zeros());
766    if zeros.first_is_cased(decimal_point) {
767        // SAFETY: safe since zeros cannot be empty due to `first_is`
768        unsafe { zeros.step_unchecked() };
769    }
770    let mut zeros_fraction = zeros.fraction_iter();
771    n_digits = n_digits.saturating_sub(zeros_fraction.skip_zeros());
772
773    // OVERFLOW
774
775    // Now, check if we explicitly overflowed.
776    if n_digits > 0 {
777        // Have more than 19 significant digits, so we overflowed.
778        many_digits = true;
779        mantissa = 0;
780        let mut integer = integer_digits.bytes::<{ FORMAT }>();
781        // Skip leading zeros, so we can use the step properly.
782        let mut integer_iter = integer.integer_iter();
783        integer_iter.skip_zeros();
784        parse_u64_digits::<_, FORMAT>(integer_iter, &mut mantissa, &mut step);
785        // NOTE: With the format feature enabled and non-contiguous iterators, we can
786        // have null fraction digits even if step was not 0. We want to make the
787        // none check as late in there as possible: any of them should
788        // short-circuit and should be determined at compile time. So, the
789        // conditions are either:
790        // 1. Step == 0
791        // 2. `cfg!(feature = "format") && !byte.is_contiguous() &&
792        //    fraction_digits.is_none()`
793        implicit_exponent = if step == 0
794            || (cfg!(feature = "format") && !byte.is_contiguous() && fraction_digits.is_none())
795        {
796            // Filled our mantissa with just the integer.
797            int_end - integer.current_count() as i64
798        } else {
799            // We know this can't be a None since we had more than 19
800            // digits previously, so we overflowed a 64-bit integer,
801            // but parsing only the integral digits produced less
802            // than 19 digits. That means we must have a decimal
803            // point, and at least 1 fractional digit.
804            let mut fraction = fraction_digits.unwrap().bytes::<{ FORMAT }>();
805            let mut fraction_iter = fraction.fraction_iter();
806            // Skip leading zeros, so we can use the step properly.
807            if mantissa == 0 {
808                fraction_iter.skip_zeros();
809            }
810            parse_u64_digits::<_, FORMAT>(fraction_iter, &mut mantissa, &mut step);
811            -(fraction.current_count() as i64)
812        };
813        if format.mantissa_radix() == format.exponent_base() {
814            exponent = implicit_exponent;
815        } else {
816            debug_assert!(bits_per_digit % bits_per_base == 0, "exponent must be a power of base");
817            exponent = implicit_exponent * bits_per_digit / bits_per_base;
818        };
819        // Add back the explicit exponent.
820        exponent += explicit_exponent;
821    }
822
823    Ok((
824        Number {
825            exponent,
826            mantissa,
827            is_negative,
828            many_digits,
829            integer: integer_digits,
830            fraction: fraction_digits,
831        },
832        end,
833    ))
834}
835
836#[inline(always)]
837pub fn parse_partial_number<'a, const FORMAT: u128>(
838    byte: Bytes<'a, FORMAT>,
839    is_negative: bool,
840    options: &Options,
841) -> Result<(Number<'a>, usize)> {
842    parse_number::<FORMAT, true>(byte, is_negative, options)
843}
844
845/// Try to parse a non-special floating point number.
846#[inline(always)]
847pub fn parse_complete_number<'a, const FORMAT: u128>(
848    byte: Bytes<'a, FORMAT>,
849    is_negative: bool,
850    options: &Options,
851) -> Result<Number<'a>> {
852    // Then have a const `IsPartial` as well
853    let length = byte.buffer_length();
854    let (float, count) = parse_number::<FORMAT, false>(byte, is_negative, options)?;
855    if count == length {
856        Ok(float)
857    } else {
858        Err(Error::InvalidDigit(count))
859    }
860}
861
862// DIGITS
863// ------
864
865/// Iteratively parse and consume digits from bytes.
866#[inline(always)]
867pub fn parse_digits<'a, Iter, Cb>(mut iter: Iter, radix: u32, mut cb: Cb)
868where
869    Iter: DigitsIter<'a>,
870    Cb: FnMut(u32),
871{
872    while let Some(&c) = iter.peek() {
873        match char_to_digit_const(c, radix) {
874            Some(v) => cb(v),
875            None => break,
876        }
877        // SAFETY: iter cannot be empty due to `iter.peek()`.
878        // NOTE: Because of the match statement, this would optimize poorly with
879        // `read_if`.
880        unsafe { iter.step_unchecked() };
881        iter.increment_count();
882    }
883}
884
885/// Iteratively parse and consume digits in intervals of 8.
886///
887/// # Preconditions
888///
889/// The iterator must be of the significant digits, not the exponent.
890#[inline(always)]
891#[cfg(not(feature = "compact"))]
892pub fn parse_8digits<'a, Iter, const FORMAT: u128>(mut iter: Iter, mantissa: &mut u64)
893where
894    Iter: DigitsIter<'a>,
895{
896    let format = NumberFormat::<{ FORMAT }> {};
897    let radix: u64 = format.radix() as u64;
898    if can_try_parse_multidigit!(iter, radix) {
899        debug_assert!(radix < 16, "radices over 16 will overflow with radix^8");
900        let radix8 = format.radix8() as u64;
901        // Can do up to 2 iterations without overflowing, however, for large
902        // inputs, this is much faster than any other alternative.
903        while let Some(v) = algorithm::try_parse_8digits::<u64, _, FORMAT>(&mut iter) {
904            *mantissa = mantissa.wrapping_mul(radix8).wrapping_add(v);
905        }
906    }
907}
908
909/// Iteratively parse and consume digits without overflowing.
910///
911/// # Preconditions
912///
913/// There must be at least `step` digits left in iterator. The iterator almost
914/// must be of the significant digits, not the exponent.
915#[cfg_attr(not(feature = "compact"), inline(always))]
916pub fn parse_u64_digits<'a, Iter, const FORMAT: u128>(
917    mut iter: Iter,
918    mantissa: &mut u64,
919    step: &mut usize,
920) where
921    Iter: DigitsIter<'a>,
922{
923    let format = NumberFormat::<{ FORMAT }> {};
924    let radix = format.radix() as u64;
925
926    // Try to parse 8 digits at a time, if we can.
927    #[cfg(not(feature = "compact"))]
928    if can_try_parse_multidigit!(iter, radix) {
929        debug_assert!(radix < 16, "radices over 16 will overflow with radix^8");
930        let radix8 = format.radix8() as u64;
931        while *step > 8 {
932            if let Some(v) = algorithm::try_parse_8digits::<u64, _, FORMAT>(&mut iter) {
933                *mantissa = mantissa.wrapping_mul(radix8).wrapping_add(v);
934                *step -= 8;
935            } else {
936                break;
937            }
938        }
939    }
940
941    // Parse single digits at a time.
942    while let Some(&c) = iter.peek() {
943        if *step > 0 {
944            let digit = char_to_valid_digit_const(c, radix as u32);
945            *mantissa = *mantissa * radix + digit as u64;
946            *step -= 1;
947            // SAFETY: safe, since `iter` cannot be empty due to `iter.peek()`.
948            unsafe { iter.step_unchecked() };
949            iter.increment_count();
950        } else {
951            break;
952        }
953    }
954}
955
956// SPECIAL
957// -------
958
959/// Determine if the input data matches the special string.
960/// If there's no match, returns 0. Otherwise, returns the byte's cursor.
961#[must_use]
962#[inline(always)]
963pub fn is_special_eq<const FORMAT: u128>(mut byte: Bytes<FORMAT>, string: &'static [u8]) -> usize {
964    let format = NumberFormat::<{ FORMAT }> {};
965    if cfg!(feature = "format") && format.case_sensitive_special() {
966        if shared::starts_with(byte.special_iter(), string.iter()) {
967            // Trim the iterator afterwards.
968            byte.special_iter().peek();
969            return byte.cursor();
970        }
971    } else if shared::starts_with_uncased(byte.special_iter(), string.iter()) {
972        // Trim the iterator afterwards.
973        byte.special_iter().peek();
974        return byte.cursor();
975    }
976    0
977}
978
979/// Parse a positive representation of a special, non-finite float.
980#[must_use]
981#[cfg_attr(not(feature = "compact"), inline(always))]
982pub fn parse_positive_special<F, const FORMAT: u128>(
983    byte: Bytes<FORMAT>,
984    options: &Options,
985) -> Option<(F, usize)>
986where
987    F: LemireFloat,
988{
989    let format = NumberFormat::<{ FORMAT }> {};
990    if cfg!(feature = "format") && format.no_special() {
991        return None;
992    }
993
994    let cursor = byte.cursor();
995    let length = byte.buffer_length() - cursor;
996    if let Some(nan_string) = options.nan_string() {
997        if length >= nan_string.len() {
998            let count = is_special_eq::<FORMAT>(byte.clone(), nan_string);
999            if count != 0 {
1000                return Some((F::NAN, count));
1001            }
1002        }
1003    }
1004    if let Some(infinity_string) = options.infinity_string() {
1005        if length >= infinity_string.len() {
1006            let count = is_special_eq::<FORMAT>(byte.clone(), infinity_string);
1007            if count != 0 {
1008                return Some((F::INFINITY, count));
1009            }
1010        }
1011    }
1012    if let Some(inf_string) = options.inf_string() {
1013        if length >= inf_string.len() {
1014            let count = is_special_eq::<FORMAT>(byte.clone(), inf_string);
1015            if count != 0 {
1016                return Some((F::INFINITY, count));
1017            }
1018        }
1019    }
1020
1021    None
1022}
1023
1024/// Parse a partial representation of a special, non-finite float.
1025#[must_use]
1026#[inline(always)]
1027pub fn parse_partial_special<F, const FORMAT: u128>(
1028    byte: Bytes<FORMAT>,
1029    is_negative: bool,
1030    options: &Options,
1031) -> Option<(F, usize)>
1032where
1033    F: LemireFloat,
1034{
1035    let (mut float, count) = parse_positive_special::<F, FORMAT>(byte, options)?;
1036    if is_negative {
1037        float = -float;
1038    }
1039    Some((float, count))
1040}
1041
1042/// Try to parse a special, non-finite float.
1043#[must_use]
1044#[inline(always)]
1045pub fn parse_special<F, const FORMAT: u128>(
1046    byte: Bytes<FORMAT>,
1047    is_negative: bool,
1048    options: &Options,
1049) -> Option<F>
1050where
1051    F: LemireFloat,
1052{
1053    let length = byte.buffer_length();
1054    if let Some((float, count)) = parse_partial_special::<F, FORMAT>(byte, is_negative, options) {
1055        if count == length {
1056            return Some(float);
1057        }
1058    }
1059    None
1060}