@@ -6,6 +6,33 @@ pub fn parse_str(literal: &str) -> Option<f64> {
66 parse_inner ( literal. trim ( ) . as_bytes ( ) )
77}
88
9+ fn strip_separators ( literal : & [ u8 ] ) -> Option < Vec < u8 > > {
10+ let mut prev = b'\0' ;
11+ let mut dup = Vec :: < u8 > :: new ( ) ;
12+ for p in literal {
13+ if * p == b'_' {
14+ // Underscores are only allowed after digits.
15+ if !prev. is_ascii_digit ( ) {
16+ return None ;
17+ }
18+ } else {
19+ dup. push ( * p) ;
20+ // Underscores are only allowed before digits.
21+ if prev == b'_' && !p. is_ascii_digit ( ) {
22+ return None ;
23+ }
24+ }
25+ prev = * p;
26+ }
27+
28+ // Underscores are not allowed at the end.
29+ if prev == b'_' {
30+ return None ;
31+ }
32+
33+ Some ( dup)
34+ }
35+
936pub fn parse_bytes ( literal : & [ u8 ] ) -> Option < f64 > {
1037 parse_inner ( trim_slice ( literal, |b| b. is_ascii_whitespace ( ) ) )
1138}
@@ -28,12 +55,16 @@ fn parse_inner(literal: &[u8]) -> Option<f64> {
2855 use lexical_parse_float:: {
2956 format:: PYTHON3_LITERAL , FromLexicalWithOptions , NumberFormatBuilder , Options ,
3057 } ;
58+
59+ // Use custom function for underline handling for now.
60+ // For further information see https://github.com/Alexhuszagh/rust-lexical/issues/96.
61+ let stripped = strip_separators ( literal) ?;
62+
3163 // lexical-core's format::PYTHON_STRING is inaccurate
3264 const PYTHON_STRING : u128 = NumberFormatBuilder :: rebuild ( PYTHON3_LITERAL )
3365 . no_special ( false )
34- . consecutive_digit_separator ( false )
3566 . build ( ) ;
36- f64:: from_lexical_with_options :: < PYTHON_STRING > ( literal , & Options :: new ( ) ) . ok ( )
67+ f64:: from_lexical_with_options :: < PYTHON_STRING > ( & stripped , & Options :: new ( ) ) . ok ( )
3768}
3869
3970pub fn is_integer ( v : f64 ) -> bool {
0 commit comments