Skip to main content

sonic_number/
lib.rs

1#![no_std]
2
3#[cfg(test)]
4extern crate std;
5
6mod arch;
7mod common;
8mod decimal;
9mod float;
10mod lemire;
11mod slow;
12pub mod swar;
13mod table;
14
15use self::{common::BiasedFp, float::RawFloat, table::POWER_OF_FIVE_128};
16pub use crate::{arch::simd_str2int, swar::swar_str2int};
17
18const FLOATING_LONGEST_DIGITS: usize = 17;
19const FLOATING_LONGEST_DIGITS_F32: usize = 9;
20const F64_BITS: u32 = 64;
21const F64_SIG_BITS: u32 = 52;
22const F64_SIG_FULL_BITS: u32 = 53;
23const F64_EXP_BIAS: i32 = 1023;
24const F64_SIG_MASK: u64 = 0x000F_FFFF_FFFF_FFFF;
25
26#[derive(Debug)]
27pub enum ParserNumber {
28    Unsigned(u64),
29    /// Always less than zero.
30    Signed(i64),
31    /// Always finite.
32    Float(f64),
33}
34
35#[derive(Debug)]
36pub enum Error {
37    InvalidNumber,
38    FloatMustBeFinite,
39}
40
41// Checked macros (with bounds check — safe for any buffer)
42macro_rules! match_digit {
43    ($data:expr, $i:expr, $pattern:pat) => {
44        $i < $data.len() && matches!($data[$i], $pattern)
45    };
46}
47macro_rules! is_digit {
48    ($data:expr, $i:expr) => {
49        $i < $data.len() && $data[$i].is_ascii_digit()
50    };
51}
52macro_rules! digit {
53    ($data:expr, $i:expr) => {
54        ($data[$i] - b'0') as u64
55    };
56}
57macro_rules! check_digit {
58    ($data:expr, $i:expr) => {
59        if !($i < $data.len() && $data[$i].is_ascii_digit()) {
60            return Err(Error::InvalidNumber);
61        }
62    };
63}
64
65// Unchecked macros (no bounds check — requires >=64 bytes padding after data)
66macro_rules! match_digit_u {
67    ($data:expr, $i:expr, $pattern:pat) => {
68        matches!(unsafe { *$data.get_unchecked($i) }, $pattern)
69    };
70}
71macro_rules! is_digit_u {
72    ($data:expr, $i:expr) => {
73        unsafe { *$data.get_unchecked($i) }.is_ascii_digit()
74    };
75}
76macro_rules! digit_u {
77    ($data:expr, $i:expr) => {
78        (unsafe { *$data.get_unchecked($i) } - b'0') as u64
79    };
80}
81macro_rules! check_digit_u {
82    ($data:expr, $i:expr) => {
83        if !(unsafe { *$data.get_unchecked($i) }.is_ascii_digit()) {
84            return Err(Error::InvalidNumber);
85        }
86    };
87}
88
89#[inline(always)]
90fn parse_exponent(data: &[u8], index: &mut usize) -> Result<i32, Error> {
91    let mut exponent: i32 = 0;
92    let mut negative = false;
93
94    if *index >= data.len() {
95        return Err(Error::InvalidNumber);
96    }
97
98    match data[*index] {
99        b'+' => *index += 1,
100        b'-' => {
101            negative = true;
102            *index += 1;
103        }
104        _ => {}
105    }
106
107    check_digit!(data, *index);
108    while exponent < 1000 && is_digit!(data, *index) {
109        exponent = digit!(data, *index) as i32 + exponent * 10;
110        *index += 1;
111    }
112    while is_digit!(data, *index) {
113        *index += 1;
114    }
115    if negative {
116        exponent = -exponent;
117    }
118    Ok(exponent)
119}
120
121const POW10_UINT: [u64; 18] = [
122    1,
123    10,
124    100,
125    1000,
126    10000,
127    100000,
128    1000000,
129    10000000,
130    100000000,
131    1000000000,
132    10000000000,
133    100000000000,
134    1000000000000,
135    10000000000000,
136    100000000000000,
137    1000000000000000,
138    10000000000000000,
139    100000000000000000,
140];
141
142// parse at most 16 digits for fraction, record the exponent.
143// because we calcaute at least the first significant digit when both normal or subnormal float
144// points
145#[inline(always)]
146fn parse_number_fraction(
147    data: &[u8],
148    index: &mut usize,
149    significant: &mut u64,
150    exponent: &mut i32,
151    need: isize,
152    dot_pos: usize,
153) -> Result<bool, Error> {
154    debug_assert!(need < FLOATING_LONGEST_DIGITS as isize);
155
156    // Use SWAR (integer pipeline) instead of SSE simd_str2int (FP pipeline).
157    // On AMD Zen, SSE maddubs/madd go through FP ports causing ALU saturation.
158    // Two-step SWAR: 8-digit batch + tolerant SWAR for remaining 1-8 digits,
159    // eliminating the scalar while-loop tail for float-heavy workloads.
160    //
161    // Note: `significant` may wrap on u64 overflow when the integer part has many
162    // digits. This is harmless — wrapping makes the fast path in `parse_float` fail,
163    // which falls back to `slow::parse_long_mantissa(raw_num)` for a correct result.
164    if need > 0 {
165        let need = need as usize;
166        unsafe {
167            let c = data.get_unchecked(*index..);
168            if need >= 8 && c.len() >= 8 && swar::is_eight_digits(c) {
169                let first8 = swar::parse_eight_digits(c) as u64;
170                let remaining = need - 8;
171                if remaining >= 8 && c.len() >= 16 && swar::is_eight_digits(&c[8..]) {
172                    let second8 = swar::parse_eight_digits(&c[8..]) as u64;
173                    *significant = *significant * POW10_UINT[16] + first8 * 100_000_000 + second8;
174                    *index += 16;
175                } else if remaining > 0 && c.len() >= 16 {
176                    // Tolerant SWAR for remaining 1-8 digits (no scalar loop)
177                    let (mut tail_val, tail_n) = swar::parse_digits_tolerant(&c[8..]);
178                    let tail_n = if tail_n > remaining {
179                        // Parsed more digits than needed — drop the excess trailing digits.
180                        tail_val /= POW10_UINT[tail_n - remaining];
181                        remaining
182                    } else {
183                        tail_n
184                    };
185                    let total = 8 + tail_n;
186                    *significant =
187                        *significant * POW10_UINT[total] + first8 * POW10_UINT[tail_n] + tail_val;
188                    *index += total;
189                } else {
190                    // c.len() < 16: not enough bytes for tolerant SWAR on tail.
191                    // Parse first 8 digits via SWAR, then scalar tail for remaining.
192                    *significant = *significant * POW10_UINT[8] + first8;
193                    *index += 8;
194                    let mut rem = remaining;
195                    while rem > 0 && is_digit!(data, *index) {
196                        *significant = *significant * 10 + digit!(data, *index);
197                        *index += 1;
198                        rem -= 1;
199                    }
200                }
201            } else {
202                let (frac, ndigits) = swar::swar_str2int(c, need);
203                *significant = *significant * POW10_UINT[ndigits] + frac;
204                *index += ndigits;
205            }
206        }
207    }
208
209    *exponent -= *index as i32 - dot_pos as i32;
210    let mut trunc = false;
211    while is_digit!(data, *index) {
212        trunc = true;
213        *index += 1;
214    }
215
216    if match_digit!(data, *index, b'e' | b'E') {
217        *index += 1;
218        *exponent += parse_exponent(data, &mut *index)?;
219    }
220    Ok(trunc)
221}
222
223#[inline(always)]
224pub fn parse_number(data: &[u8], index: &mut usize, negative: bool) -> Result<ParserNumber, Error> {
225    let mut significant: u64 = 0;
226    let mut exponent: i32 = 0;
227    let mut trunc = false;
228    // Checked slice: validates *index <= data.len() (panics otherwise).
229    // This bounds guarantee is relied upon by the unchecked slice at the SWAR branch below.
230    let raw_num = &data[*index..];
231
232    if match_digit!(data, *index, b'0') {
233        *index += 1;
234
235        if *index >= data.len() || !matches!(data[*index], b'.' | b'e' | b'E') {
236            // view -0 as float number
237            if negative {
238                return Ok(ParserNumber::Float(0.0));
239            }
240            return Ok(ParserNumber::Unsigned(0));
241        }
242
243        // deal with 0e123 or 0.000e123
244        match data[*index] {
245            b'.' => {
246                *index += 1;
247                let dot_pos = *index;
248                check_digit!(data, *index);
249                while match_digit!(data, *index, b'0') {
250                    *index += 1;
251                }
252                // special case: 0.000e123
253                if match_digit!(data, *index, b'e' | b'E') {
254                    *index += 1;
255                    if match_digit!(data, *index, b'-' | b'+') {
256                        *index += 1;
257                    }
258                    check_digit!(data, *index);
259                    while is_digit!(data, *index) {
260                        *index += 1;
261                    }
262                    return Ok(ParserNumber::Float(0.0));
263                }
264
265                // we calculate the first digit here for two reasons:
266                // 1. fastpath for small float number
267                // 2. we only need parse at most 16 digits in parse_number_fraction
268                // and it is friendly for simd
269                if !is_digit!(data, *index) {
270                    return Ok(ParserNumber::Float(0.0));
271                }
272
273                significant = digit!(data, *index);
274                *index += 1;
275
276                if is_digit!(data, *index) {
277                    let need = FLOATING_LONGEST_DIGITS as isize - 1;
278                    trunc = parse_number_fraction(
279                        data,
280                        index,
281                        &mut significant,
282                        &mut exponent,
283                        need,
284                        dot_pos,
285                    )?;
286                } else {
287                    exponent -= *index as i32 - dot_pos as i32;
288                    if match_digit!(data, *index, b'e' | b'E') {
289                        *index += 1;
290                        exponent += parse_exponent(data, &mut *index)?;
291                    }
292                }
293            }
294            b'e' | b'E' => {
295                *index += 1;
296                if match_digit!(data, *index, b'-' | b'+') {
297                    *index += 1;
298                }
299                check_digit!(data, *index);
300                while is_digit!(data, *index) {
301                    *index += 1;
302                }
303                return Ok(ParserNumber::Float(0.0));
304            }
305            _ => unreachable!("unreachable branch in parse_number_unchecked"),
306        }
307    } else {
308        // SWAR-optimized integer digit parsing.
309        let digit_start = *index;
310        // Safety: *index <= data.len() is guaranteed by the checked slice `&data[*index..]`
311        // above (line 223), which would have panicked on out-of-bounds.
312        let remaining = unsafe { data.get_unchecked(*index..) };
313
314        let digits_cnt;
315        if remaining.len() >= 8 && swar::is_eight_digits(remaining) {
316            // SWAR path: first 8 bytes are all digits.
317            significant = swar::parse_eight_digits(remaining) as u64;
318            *index += 8;
319
320            // Try second 8-digit batch
321            if data.len() - *index >= 8 && swar::is_eight_digits(&data[*index..]) {
322                significant =
323                    significant * 100_000_000 + swar::parse_eight_digits(&data[*index..]) as u64;
324                *index += 8;
325            }
326
327            // Scalar tail for remaining digits (at most 3 more to stay within u64)
328            while (*index - digit_start) < 19 && is_digit!(data, *index) {
329                significant = significant * 10 + digit!(data, *index);
330                *index += 1;
331            }
332            digits_cnt = *index - digit_start;
333
334            // Handle overflow digits beyond 19
335            while is_digit!(data, *index) {
336                exponent += 1;
337                *index += 1;
338                trunc = true;
339            }
340        } else {
341            // Scalar path: fewer than 8 leading digits or short input.
342            // Includes single-digit fast path — if only one digit and not followed
343            // by '.', 'e', 'E', return immediately without further checks.
344            if !is_digit!(data, *index) {
345                return Err(Error::InvalidNumber);
346            }
347            significant = digit!(data, *index);
348            *index += 1;
349
350            if is_digit!(data, *index) {
351                // 2-7 digits: continue scalar loop
352                while is_digit!(data, *index) {
353                    significant = significant * 10 + digit!(data, *index);
354                    *index += 1;
355                }
356                digits_cnt = *index - digit_start;
357            } else if !match_digit!(data, *index, b'.' | b'e' | b'E') {
358                // Single digit integer — fast return
359                if negative {
360                    return Ok(ParserNumber::Signed(-(significant as i64)));
361                }
362                return Ok(ParserNumber::Unsigned(significant));
363            } else {
364                digits_cnt = 1;
365            }
366        }
367        if match_digit!(data, *index, b'e' | b'E') {
368            // parse exponent
369            *index += 1;
370            exponent += parse_exponent(data, index)?;
371        } else if match_digit!(data, *index, b'.') {
372            *index += 1;
373            check_digit!(data, *index);
374            let dot_pos = *index;
375
376            if digits_cnt < 8 {
377                // Short integer part — continue scalar accumulation into fraction.
378                // Avoids SIMD setup + POW10 table multiplication overhead.
379                // yyjson uses this approach: sig = sig*10+digit continuously.
380                let mut need = FLOATING_LONGEST_DIGITS as isize - digits_cnt as isize;
381                while need > 0 && is_digit!(data, *index) {
382                    significant = significant * 10 + digit!(data, *index);
383                    *index += 1;
384                    need -= 1;
385                }
386                exponent -= *index as i32 - dot_pos as i32;
387                while is_digit!(data, *index) {
388                    trunc = true;
389                    *index += 1;
390                }
391                if match_digit!(data, *index, b'e' | b'E') {
392                    *index += 1;
393                    exponent += parse_exponent(data, &mut *index)?;
394                }
395            } else {
396                // Long integer part — use SIMD fraction parsing
397                let need = FLOATING_LONGEST_DIGITS as isize - digits_cnt as isize;
398                trunc = parse_number_fraction(
399                    data,
400                    index,
401                    &mut significant,
402                    &mut exponent,
403                    need,
404                    dot_pos,
405                )?;
406            }
407        } else {
408            // parse integer, all parse has finished.
409            if exponent == 0 {
410                if negative {
411                    if significant > (1u64 << 63) {
412                        return Ok(ParserNumber::Float(-(significant as f64)));
413                    } else {
414                        // if significant is 0x8000_0000_0000_0000, it will overflow here.
415                        // so, we must use wrapping_sub here.
416                        return Ok(ParserNumber::Signed(0_i64.wrapping_sub(significant as i64)));
417                    }
418                } else {
419                    return Ok(ParserNumber::Unsigned(significant));
420                }
421            } else if exponent == 1 {
422                // now we get 20 digits, it maybe overflow for uint64
423                let last = digit!(data, *index - 1);
424                let (out, ov0) = significant.overflowing_mul(10);
425                let (out, ov1) = out.overflowing_add(last);
426                if !ov0 && !ov1 {
427                    // negative must be overflow here.
428                    significant = out;
429                    if negative {
430                        return Ok(ParserNumber::Float(-(significant as f64)));
431                    } else {
432                        return Ok(ParserNumber::Unsigned(significant));
433                    }
434                }
435            }
436            trunc = true;
437        }
438    }
439
440    // raw_num is pass-through for fallback parsing logic
441    parse_float(significant, exponent, negative, trunc, raw_num)
442}
443
444#[allow(unused_assignments)]
445#[inline(always)]
446pub fn parse_float32(data: &[u8], index: &mut usize, negative: bool) -> Result<f32, Error> {
447    let mut significant: u64 = 0;
448    let mut exponent: i32 = 0;
449    let mut trunc = false;
450    let raw_num = &data[*index..];
451
452    if match_digit!(data, *index, b'0') {
453        *index += 1;
454
455        if *index >= data.len() || !matches!(data[*index], b'.' | b'e' | b'E') {
456            let zero = 0.0f32;
457            return Ok(if negative { -zero } else { zero });
458        }
459
460        match data[*index] {
461            b'.' => {
462                *index += 1;
463                let dot_pos = *index;
464                check_digit!(data, *index);
465                while match_digit!(data, *index, b'0') {
466                    *index += 1;
467                }
468
469                if match_digit!(data, *index, b'e' | b'E') {
470                    *index += 1;
471                    if match_digit!(data, *index, b'-' | b'+') {
472                        *index += 1;
473                    }
474                    check_digit!(data, *index);
475                    while is_digit!(data, *index) {
476                        *index += 1;
477                    }
478                    let zero = 0.0f32;
479                    return Ok(if negative { -zero } else { zero });
480                }
481
482                if !is_digit!(data, *index) {
483                    let zero = 0.0f32;
484                    return Ok(if negative { -zero } else { zero });
485                }
486
487                significant = digit!(data, *index);
488                *index += 1;
489
490                if is_digit!(data, *index) {
491                    let need = FLOATING_LONGEST_DIGITS_F32 as isize - 1;
492                    trunc = parse_number_fraction(
493                        data,
494                        index,
495                        &mut significant,
496                        &mut exponent,
497                        need,
498                        dot_pos,
499                    )?;
500                } else {
501                    exponent -= *index as i32 - dot_pos as i32;
502                    if match_digit!(data, *index, b'e' | b'E') {
503                        *index += 1;
504                        exponent += parse_exponent(data, &mut *index)?;
505                    }
506                }
507            }
508            b'e' | b'E' => {
509                *index += 1;
510                if match_digit!(data, *index, b'-' | b'+') {
511                    *index += 1;
512                }
513                check_digit!(data, *index);
514                while is_digit!(data, *index) {
515                    *index += 1;
516                }
517                let zero = 0.0f32;
518                return Ok(if negative { -zero } else { zero });
519            }
520            _ => unreachable!("unreachable branch in parse_float32"),
521        }
522    } else {
523        let digit_start = *index;
524        let remaining = unsafe { data.get_unchecked(*index..) };
525
526        let digits_cnt;
527        if remaining.len() >= 8 && swar::is_eight_digits(remaining) {
528            significant = swar::parse_eight_digits(remaining) as u64;
529            *index += 8;
530
531            if data.len() - *index >= 8 && swar::is_eight_digits(&data[*index..]) {
532                significant =
533                    significant * 100_000_000 + swar::parse_eight_digits(&data[*index..]) as u64;
534                *index += 8;
535            }
536
537            while (*index - digit_start) < 19 && is_digit!(data, *index) {
538                significant = significant * 10 + digit!(data, *index);
539                *index += 1;
540            }
541            digits_cnt = *index - digit_start;
542
543            while is_digit!(data, *index) {
544                exponent += 1;
545                *index += 1;
546                trunc = true;
547            }
548        } else {
549            if !is_digit!(data, *index) {
550                return Err(Error::InvalidNumber);
551            }
552            significant = digit!(data, *index);
553            *index += 1;
554
555            if is_digit!(data, *index) {
556                while is_digit!(data, *index) {
557                    significant = significant * 10 + digit!(data, *index);
558                    *index += 1;
559                }
560                digits_cnt = *index - digit_start;
561            } else if !match_digit!(data, *index, b'.' | b'e' | b'E') {
562                let mut float = significant as f32;
563                if negative {
564                    float = -float;
565                }
566                return Ok(float);
567            } else {
568                digits_cnt = 1;
569            }
570        }
571
572        if match_digit!(data, *index, b'e' | b'E') {
573            *index += 1;
574            exponent += parse_exponent(data, index)?;
575        } else if match_digit!(data, *index, b'.') {
576            *index += 1;
577            check_digit!(data, *index);
578            let dot_pos = *index;
579
580            if digits_cnt < 8 {
581                let mut need = FLOATING_LONGEST_DIGITS_F32 as isize - digits_cnt as isize;
582                while need > 0 && is_digit!(data, *index) {
583                    significant = significant * 10 + digit!(data, *index);
584                    *index += 1;
585                    need -= 1;
586                }
587                exponent -= *index as i32 - dot_pos as i32;
588                while is_digit!(data, *index) {
589                    trunc = true;
590                    *index += 1;
591                }
592                if match_digit!(data, *index, b'e' | b'E') {
593                    *index += 1;
594                    exponent += parse_exponent(data, &mut *index)?;
595                }
596            } else {
597                let need = FLOATING_LONGEST_DIGITS_F32 as isize - digits_cnt as isize;
598                trunc = parse_number_fraction(
599                    data,
600                    index,
601                    &mut significant,
602                    &mut exponent,
603                    need,
604                    dot_pos,
605                )?;
606            }
607        } else {
608            if exponent == 0 {
609                let mut float = significant as f32;
610                if negative {
611                    float = -float;
612                }
613                return Ok(float);
614            } else if exponent == 1 {
615                let last = digit!(data, *index - 1);
616                let (out, ov0) = significant.overflowing_mul(10);
617                let (out, ov1) = out.overflowing_add(last);
618                if !ov0 && !ov1 {
619                    significant = out;
620                    let mut float = significant as f32;
621                    if negative {
622                        float = -float;
623                    }
624                    return Ok(float);
625                }
626            }
627            trunc = true;
628        }
629    }
630
631    parse_float_generic::<f32>(significant, exponent, negative, trunc, raw_num)
632}
633
634/// Unchecked version — caller must ensure data has >=64 bytes padding.
635#[inline(always)]
636pub unsafe fn parse_number_unchecked(
637    data: &[u8],
638    index: &mut usize,
639    negative: bool,
640) -> Result<ParserNumber, Error> {
641    let mut significant: u64 = 0;
642    let mut exponent: i32 = 0;
643    let mut trunc = false;
644    let raw_num = unsafe { data.get_unchecked(*index..) };
645
646    if match_digit_u!(data, *index, b'0') {
647        *index += 1;
648
649        if !match_digit_u!(data, *index, b'.' | b'e' | b'E') {
650            // view -0 as float number
651            if negative {
652                return Ok(ParserNumber::Float(0.0));
653            }
654            return Ok(ParserNumber::Unsigned(0));
655        }
656
657        // deal with 0e123 or 0.000e123
658        match data[*index] {
659            b'.' => {
660                *index += 1;
661                let dot_pos = *index;
662                check_digit_u!(data, *index);
663                while match_digit_u!(data, *index, b'0') {
664                    *index += 1;
665                }
666                // special case: 0.000e123
667                if match_digit_u!(data, *index, b'e' | b'E') {
668                    *index += 1;
669                    if match_digit_u!(data, *index, b'-' | b'+') {
670                        *index += 1;
671                    }
672                    check_digit_u!(data, *index);
673                    while is_digit_u!(data, *index) {
674                        *index += 1;
675                    }
676                    return Ok(ParserNumber::Float(0.0));
677                }
678
679                // we calculate the first digit here for two reasons:
680                // 1. fastpath for small float number
681                // 2. we only need parse at most 16 digits in parse_number_fraction
682                // and it is friendly for simd
683                if !is_digit_u!(data, *index) {
684                    return Ok(ParserNumber::Float(0.0));
685                }
686
687                significant = digit_u!(data, *index);
688                *index += 1;
689
690                if is_digit_u!(data, *index) {
691                    let need = FLOATING_LONGEST_DIGITS as isize - 1;
692                    trunc = parse_number_fraction(
693                        data,
694                        index,
695                        &mut significant,
696                        &mut exponent,
697                        need,
698                        dot_pos,
699                    )?;
700                } else {
701                    exponent -= *index as i32 - dot_pos as i32;
702                    if match_digit_u!(data, *index, b'e' | b'E') {
703                        *index += 1;
704                        exponent += parse_exponent(data, &mut *index)?;
705                    }
706                }
707            }
708            b'e' | b'E' => {
709                *index += 1;
710                if match_digit_u!(data, *index, b'-' | b'+') {
711                    *index += 1;
712                }
713                check_digit_u!(data, *index);
714                while is_digit_u!(data, *index) {
715                    *index += 1;
716                }
717                return Ok(ParserNumber::Float(0.0));
718            }
719            _ => unreachable!("unreachable branch in parse_number_unchecked"),
720        }
721    } else {
722        // SWAR-optimized integer digit parsing.
723        let digit_start = *index;
724        let remaining = unsafe { data.get_unchecked(*index..) };
725
726        let digits_cnt;
727        if remaining.len() >= 8 && swar::is_eight_digits(remaining) {
728            // SWAR path: first 8 bytes are all digits.
729            significant = swar::parse_eight_digits(remaining) as u64;
730            *index += 8;
731
732            // Try second 8-digit batch
733            if data.len() - *index >= 8
734                && swar::is_eight_digits(unsafe { data.get_unchecked(*index..) })
735            {
736                significant = significant * 100_000_000
737                    + swar::parse_eight_digits(unsafe { data.get_unchecked(*index..) }) as u64;
738                *index += 8;
739            }
740
741            // Scalar tail for remaining digits (at most 3 more to stay within u64)
742            while (*index - digit_start) < 19 && is_digit_u!(data, *index) {
743                significant = significant * 10 + digit_u!(data, *index);
744                *index += 1;
745            }
746            digits_cnt = *index - digit_start;
747
748            // Handle overflow digits beyond 19
749            while is_digit_u!(data, *index) {
750                exponent += 1;
751                *index += 1;
752                trunc = true;
753            }
754        } else {
755            // Scalar path: fewer than 8 leading digits or short input.
756            // Includes single-digit fast path — if only one digit and not followed
757            // by '.', 'e', 'E', return immediately without further checks.
758            if !is_digit_u!(data, *index) {
759                return Err(Error::InvalidNumber);
760            }
761            significant = digit_u!(data, *index);
762            *index += 1;
763
764            if is_digit_u!(data, *index) {
765                // 2-7 digits: continue scalar loop
766                while is_digit_u!(data, *index) {
767                    significant = significant * 10 + digit_u!(data, *index);
768                    *index += 1;
769                }
770                digits_cnt = *index - digit_start;
771            } else if !match_digit_u!(data, *index, b'.' | b'e' | b'E') {
772                // Single digit integer — fast return
773                if negative {
774                    return Ok(ParserNumber::Signed(-(significant as i64)));
775                }
776                return Ok(ParserNumber::Unsigned(significant));
777            } else {
778                digits_cnt = 1;
779            }
780        }
781        if match_digit_u!(data, *index, b'e' | b'E') {
782            // parse exponent
783            *index += 1;
784            exponent += parse_exponent(data, index)?;
785        } else if match_digit_u!(data, *index, b'.') {
786            *index += 1;
787            check_digit_u!(data, *index);
788            let dot_pos = *index;
789
790            // parse fraction
791            let need = FLOATING_LONGEST_DIGITS as isize - digits_cnt as isize;
792            trunc =
793                parse_number_fraction(data, index, &mut significant, &mut exponent, need, dot_pos)?;
794        } else {
795            // parse integer, all parse has finished.
796            if exponent == 0 {
797                if negative {
798                    if significant > (1u64 << 63) {
799                        return Ok(ParserNumber::Float(-(significant as f64)));
800                    } else {
801                        // if significant is 0x8000_0000_0000_0000, it will overflow here.
802                        // so, we must use wrapping_sub here.
803                        return Ok(ParserNumber::Signed(0_i64.wrapping_sub(significant as i64)));
804                    }
805                } else {
806                    return Ok(ParserNumber::Unsigned(significant));
807                }
808            } else if exponent == 1 {
809                // now we get 20 digits, it maybe overflow for uint64
810                let last = digit_u!(data, *index - 1);
811                let (out, ov0) = significant.overflowing_mul(10);
812                let (out, ov1) = out.overflowing_add(last);
813                if !ov0 && !ov1 {
814                    // negative must be overflow here.
815                    significant = out;
816                    if negative {
817                        return Ok(ParserNumber::Float(-(significant as f64)));
818                    } else {
819                        return Ok(ParserNumber::Unsigned(significant));
820                    }
821                }
822            }
823            trunc = true;
824        }
825    }
826
827    // raw_num is pass-through for fallback parsing logic
828    parse_float(significant, exponent, negative, trunc, raw_num)
829}
830
831#[inline(always)]
832fn parse_float(
833    significant: u64,
834    exponent: i32,
835    negative: bool,
836    trunc: bool,
837    raw_num: &[u8],
838) -> Result<ParserNumber, Error> {
839    // parse double fast
840    if significant < (1u64 << F64_SIG_FULL_BITS) && (-22..=(22 + 15)).contains(&exponent) {
841        if let Some(mut float) = parse_float_fast(exponent, significant) {
842            if negative {
843                float = -float;
844            }
845            return Ok(ParserNumber::Float(float));
846        }
847    }
848
849    if !trunc && exponent > (-308 + 1) && exponent < (308 - 20) {
850        if let Some(raw) = parse_floating_normal_fast(exponent, significant) {
851            let mut float = f64::from_u64_bits(raw);
852            if negative {
853                float = -float;
854            }
855            return Ok(ParserNumber::Float(float));
856        }
857    }
858
859    // If significant digits were truncated, then we can have rounding error
860    // only if `mantissa + 1` produces a different result. We also avoid
861    // redundantly using the Eisel-Lemire algorithm if it was unable to
862    // correctly round on the first pass.
863    let exponent = exponent as i64;
864    let mut fp = lemire::compute_float::<f64>(exponent, significant);
865    if trunc && fp.e >= 0 && fp != lemire::compute_float::<f64>(exponent, significant + 1) {
866        fp.e = -1;
867    }
868
869    // Unable to correctly round the float using the Eisel-Lemire algorithm.
870    // Fallback to a slower, but always correct algorithm.
871    if fp.e < 0 {
872        fp = slow::parse_long_mantissa::<f64>(raw_num);
873    }
874
875    let mut float = biased_fp_to_float::<f64>(fp);
876    if negative {
877        float = -float;
878    }
879
880    // check inf for float
881    if float.is_infinite() {
882        return Err(Error::FloatMustBeFinite);
883    }
884    Ok(ParserNumber::Float(float))
885}
886
887#[inline(always)]
888fn parse_float_generic<T: RawFloat>(
889    significant: u64,
890    exponent: i32,
891    negative: bool,
892    trunc: bool,
893    raw_num: &[u8],
894) -> Result<T, Error> {
895    if let Some(mut float) = parse_float_fast_generic::<T>(exponent, significant) {
896        if negative {
897            float = -float;
898        }
899        return Ok(float);
900    }
901
902    let exponent = exponent as i64;
903    let mut fp = lemire::compute_float::<T>(exponent, significant);
904    if trunc && fp.e >= 0 && fp != lemire::compute_float::<T>(exponent, significant + 1) {
905        fp.e = -1;
906    }
907
908    if fp.e < 0 {
909        fp = slow::parse_long_mantissa::<T>(raw_num);
910    }
911
912    let mut float = biased_fp_to_float::<T>(fp);
913    if negative {
914        float = -float;
915    }
916
917    if matches!(float.classify(), core::num::FpCategory::Infinite) {
918        return Err(Error::FloatMustBeFinite);
919    }
920    Ok(float)
921}
922
923// This function is modified from yyjson
924#[inline(always)]
925fn parse_floating_normal_fast(exp10: i32, man: u64) -> Option<u64> {
926    let (mut hi, lo, hi2, add, bits);
927    let mut exp2: i32;
928    let mut exact = false;
929    let idx = exp10 + 342;
930    let sig2_ext = POWER_OF_FIVE_128[idx as usize].1;
931    let sig2 = POWER_OF_FIVE_128[idx as usize].0;
932
933    let mut lz = man.leading_zeros();
934    let sig1 = man << lz;
935    exp2 = ((217706 * exp10 - 4128768) >> 16) - lz as i32;
936
937    (lo, hi) = lemire::full_multiplication(sig1, sig2);
938
939    bits = hi & ((1u64 << (64 - 54 - 1)) - 1);
940    if bits.wrapping_sub(1) < ((1u64 << (64 - 54 - 1)) - 2) {
941        exact = true;
942    } else {
943        (_, hi2) = lemire::full_multiplication(sig1, sig2_ext);
944        // not need warring overflow here
945        add = lo.wrapping_add(hi2);
946        if add + 1 > 1u64 {
947            let carry = add < lo || add < hi2;
948            hi += carry as u64;
949            exact = true;
950        }
951    }
952
953    if exact {
954        lz = if hi < (1u64 << 63) { 1 } else { 0 };
955        hi <<= lz;
956        exp2 -= lz as i32;
957        exp2 += 64;
958
959        let round_up = (hi & (1u64 << (64 - 54))) > 0;
960        hi = hi.wrapping_add(if round_up { 1u64 << (64 - 54) } else { 0 });
961
962        if hi < (1u64 << (64 - 54)) {
963            hi = 1u64 << 63;
964            exp2 += 1;
965        }
966
967        hi >>= F64_BITS - F64_SIG_FULL_BITS;
968        exp2 += F64_BITS as i32 - F64_SIG_FULL_BITS as i32 + F64_SIG_BITS as i32;
969        exp2 += F64_EXP_BIAS;
970        let raw = ((exp2 as u64) << F64_SIG_BITS) | (hi & F64_SIG_MASK);
971        return Some(raw);
972    }
973    None
974}
975
976#[inline(always)]
977/// Converts a `BiasedFp` to the closest machine float type.
978fn biased_fp_to_float<T: RawFloat>(x: BiasedFp) -> T {
979    let mut word = x.f;
980    word |= (x.e as u64) << T::MANTISSA_EXPLICIT_BITS;
981    T::from_u64_bits(word)
982}
983
984#[inline(always)]
985fn parse_float_fast_generic<T: RawFloat>(mut exp10: i32, mut significant: u64) -> Option<T> {
986    if significant > T::MAX_MANTISSA_FAST_PATH {
987        return None;
988    }
989
990    let exp10_i64 = exp10 as i64;
991    if exp10_i64 < T::MIN_EXPONENT_FAST_PATH || exp10_i64 > T::MAX_EXPONENT_DISGUISED_FAST_PATH {
992        return None;
993    }
994
995    if exp10_i64 > T::MAX_EXPONENT_FAST_PATH {
996        let shift = (exp10_i64 - T::MAX_EXPONENT_FAST_PATH) as usize;
997        let pow10 = *POW10_UINT.get(shift)?;
998        significant = significant.checked_mul(pow10)?;
999        if significant > T::MAX_MANTISSA_FAST_PATH {
1000            return None;
1001        }
1002        exp10 = T::MAX_EXPONENT_FAST_PATH as i32;
1003    }
1004
1005    let mut float = T::from_u64(significant);
1006    if exp10 > 0 {
1007        float = float * T::pow10_fast_path(exp10 as usize);
1008    } else if exp10 < 0 {
1009        float = float / T::pow10_fast_path((-exp10) as usize);
1010    }
1011    Some(float)
1012}
1013
1014#[inline(always)]
1015fn parse_float_fast(exp10: i32, significant: u64) -> Option<f64> {
1016    let mut d = significant as f64;
1017    if exp10 > 0 {
1018        if exp10 > 22 {
1019            d *= POW10_FLOAT[exp10 as usize - 22];
1020            if (-1e15..=1e15).contains(&d) {
1021                Some(d * POW10_FLOAT[22])
1022            } else {
1023                None
1024            }
1025        } else {
1026            Some(d * POW10_FLOAT[exp10 as usize])
1027        }
1028    } else {
1029        Some(d / POW10_FLOAT[(-exp10) as usize])
1030    }
1031}
1032
1033const POW10_FLOAT: [f64; 23] = [
1034    /* <= the connvertion to double is not exact when less than 1 => */ 1e-000, 1e+001,
1035    1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011, 1e+012, 1e+013,
1036    1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021,
1037    1e+022, /* <= the connvertion to double is not exact when larger,  => */
1038];
1039
1040#[cfg(test)]
1041mod test {
1042    use crate::{parse_float32, parse_number, ParserNumber};
1043
1044    fn test_parse_ok(input: &str, expect: f64) {
1045        assert_eq!(input.parse::<f64>().unwrap(), expect);
1046
1047        let mut data = input.as_bytes().to_vec();
1048        data.push(b' ');
1049        let mut index = 0;
1050        let num = parse_number(&data, &mut index, false).unwrap();
1051        assert!(
1052            matches!(num, ParserNumber::Float(f) if f == expect),
1053            "parsed is {:?} failed num is {}",
1054            num,
1055            input
1056        );
1057        assert_eq!(data[index], b' ', "failed num is {}", input);
1058    }
1059
1060    fn test_parse_int_ok(input: &str, expected: u64) {
1061        let mut data = input.as_bytes().to_vec();
1062        data.push(b' ');
1063        let mut index = 0;
1064        let num = parse_number(&data, &mut index, false).unwrap();
1065        assert!(
1066            matches!(num, ParserNumber::Unsigned(v) if v == expected),
1067            "input {} parsed as {:?}, expected Unsigned({})",
1068            input,
1069            num,
1070            expected
1071        );
1072        assert_eq!(data[index], b' ', "trailing byte for {}", input);
1073    }
1074
1075    fn test_parse_f32_ok(input: &str, expect: f32) {
1076        assert_eq!(input.parse::<f32>().unwrap().to_bits(), expect.to_bits());
1077
1078        let mut data = input.as_bytes().to_vec();
1079        data.push(b' ');
1080        let mut index = if input.starts_with('-') { 1 } else { 0 };
1081        let num = parse_float32(&data, &mut index, input.starts_with('-')).unwrap();
1082        assert_eq!(
1083            num.to_bits(),
1084            expect.to_bits(),
1085            "parsed is {:?} failed num is {}",
1086            num,
1087            input
1088        );
1089        assert_eq!(data[index], b' ', "failed num is {}", input);
1090    }
1091
1092    fn test_parse_f32_finite_err(input: &str) {
1093        let mut data = input.as_bytes().to_vec();
1094        data.push(b' ');
1095        let mut index = if input.starts_with('-') { 1 } else { 0 };
1096        let err = parse_float32(&data, &mut index, input.starts_with('-')).unwrap_err();
1097        assert!(
1098            matches!(err, crate::Error::FloatMustBeFinite),
1099            "input {} returned {:?}",
1100            input,
1101            err
1102        );
1103    }
1104
1105    fn test_parse_signed_ok(input: &str, expected: i64) {
1106        let mut data = input.as_bytes().to_vec();
1107        data.push(b' ');
1108        let mut index = 1; // skip '-'
1109        let num = parse_number(&data, &mut index, true).unwrap();
1110        assert!(
1111            matches!(num, ParserNumber::Signed(v) if v == expected),
1112            "input {} parsed as {:?}, expected Signed({})",
1113            input,
1114            num,
1115            expected
1116        );
1117    }
1118
1119    #[test]
1120    fn test_parse_number_integers() {
1121        // Small integers (scalar fallback path, remaining < 8)
1122        test_parse_int_ok("0", 0);
1123        test_parse_int_ok("1", 1);
1124        test_parse_int_ok("42", 42);
1125        test_parse_int_ok("123", 123);
1126        test_parse_int_ok("1234", 1234);
1127        test_parse_int_ok("12345", 12345);
1128        test_parse_int_ok("123456", 123456);
1129        test_parse_int_ok("1234567", 1234567);
1130        // 8-digit (first SWAR batch boundary)
1131        test_parse_int_ok("12345678", 12345678);
1132        test_parse_int_ok("99999999", 99999999);
1133        // 9-15 digits (SWAR + scalar tail)
1134        test_parse_int_ok("123456789", 123456789);
1135        test_parse_int_ok("1234567890", 1234567890);
1136        test_parse_int_ok("123456789012345", 123456789012345);
1137        // 16 digits (two SWAR batches)
1138        test_parse_int_ok("1234567890123456", 1234567890123456);
1139        // 17-19 digits (two SWAR + scalar tail)
1140        test_parse_int_ok("12345678901234567", 12345678901234567);
1141        test_parse_int_ok("123456789012345678", 123456789012345678);
1142        test_parse_int_ok("1234567890123456789", 1234567890123456789);
1143        // u64::MAX
1144        test_parse_int_ok("18446744073709551615", u64::MAX);
1145        // Negative integers
1146        test_parse_signed_ok("-1", -1);
1147        test_parse_signed_ok("-12345678", -12345678);
1148        test_parse_signed_ok("-1234567890123456789", -1234567890123456789);
1149        test_parse_signed_ok("-9223372036854775808", i64::MIN);
1150    }
1151
1152    #[test]
1153    fn test_parse_number_overflow_to_float() {
1154        // > 20 digits → float
1155        test_parse_ok("33333333333333333333", 3.333333333333333e19);
1156        test_parse_ok("123456789012345678901", 1.2345678901234568e20);
1157        // Truncated integer without dot
1158        test_parse_ok("12448139190673828122020e-47", 1.244813919067383e-25);
1159        test_parse_ok(
1160            "3469446951536141862700000000000000000e-62",
1161            3.469446951536142e-26,
1162        );
1163    }
1164
1165    #[test]
1166    fn test_parse_float() {
1167        test_parse_ok("0.0", 0.0);
1168        test_parse_ok("0.01", 0.01);
1169        test_parse_ok("0.1", 0.1);
1170        test_parse_ok("0.12", 0.12);
1171        test_parse_ok("0.123", 0.123);
1172        test_parse_ok("0.1234", 0.1234);
1173        test_parse_ok("0.12345", 0.12345);
1174        test_parse_ok("0.123456", 0.123456);
1175        test_parse_ok("0.1234567", 0.1234567);
1176        test_parse_ok("0.12345678", 0.12345678);
1177        test_parse_ok("0.123456789", 0.123456789);
1178        test_parse_ok("0.1234567890", 0.1234567890);
1179        test_parse_ok("0.10000000149011612", 0.10000000149011612);
1180        test_parse_ok("0.06411743306171047", 0.06411743306171047);
1181
1182        test_parse_ok("0e-1", 0e-1);
1183        test_parse_ok("0e+1000000", 0e+1000000);
1184        test_parse_ok("0.001e-1", 0.001e-1);
1185        test_parse_ok("0.001e+123", 0.001e+123);
1186        test_parse_ok(
1187            "0.000000000000000000000000001e+123",
1188            0.000000000000000000000000001e+123,
1189        );
1190
1191        test_parse_ok("1.0", 1.0);
1192        test_parse_ok("1350.0", 1350.0);
1193        test_parse_ok("1.10000000149011612", 1.1000000014901161);
1194
1195        // 8+ integer digits + fraction: exercises parse_number_fraction
1196        // with digits_cnt >= 8, need <= 9, fraction slice may be < 16 bytes.
1197        test_parse_ok("12345678.123456789", 12345678.123456789);
1198        test_parse_ok("12345678.1", 12345678.1);
1199        test_parse_ok("12345678.12345678", 12345678.12345678);
1200        test_parse_ok("123456789.123456", 123456789.123456);
1201        test_parse_ok("1234567890.1234567", 1234567890.1234567);
1202        test_parse_ok("99999999.99999999", 99999999.99999999);
1203
1204        test_parse_ok("1e0", 1e0);
1205        test_parse_ok("1.0e0", 1.0e0);
1206        test_parse_ok("1.0e+0", 1.0e+0);
1207        test_parse_ok("1.001e-123", 1.001e-123);
1208        test_parse_ok("10000000149011610000.0e-123", 1.000_000_014_901_161e-104);
1209        test_parse_ok(
1210            "10000000149011612123.001e-123",
1211            1.000_000_014_901_161_2e-104,
1212        );
1213        test_parse_ok("33333333333333333333", 3.333333333333333e19);
1214        test_parse_ok("135e-12", 135e-12);
1215
1216        // test truncated float number without dot
1217        test_parse_ok("12448139190673828122020e-47", 1.244813919067383e-25);
1218        test_parse_ok(
1219            "3469446951536141862700000000000000000e-62",
1220            3.469446951536142e-26,
1221        );
1222    }
1223
1224    #[test]
1225    fn test_parse_float32() {
1226        test_parse_f32_ok("0", 0.0);
1227        test_parse_f32_ok("-0", -0.0);
1228        test_parse_f32_ok("1", 1.0);
1229        test_parse_f32_ok("0.1", 0.1);
1230        test_parse_f32_ok("1.23", 1.23);
1231        test_parse_f32_ok("100e11", "100e11".parse().unwrap());
1232        test_parse_f32_ok(
1233            "17005001.000000000000130",
1234            "17005001.000000000000130".parse().unwrap(),
1235        );
1236        test_parse_f32_ok("3.4028235e38", "3.4028235e38".parse().unwrap());
1237        test_parse_f32_ok("1.17549435e-38", "1.17549435e-38".parse().unwrap());
1238        test_parse_f32_ok(
1239            "12448139190673828122020e-47",
1240            "12448139190673828122020e-47".parse().unwrap(),
1241        );
1242        test_parse_f32_finite_err("3.4028236e38");
1243        test_parse_f32_finite_err("1e39");
1244    }
1245}