@@ -6,6 +6,33 @@ pub fn parse_str(literal: &str) -> Option<f64> {
6
6
parse_inner ( literal. trim ( ) . as_bytes ( ) )
7
7
}
8
8
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
+
9
36
pub fn parse_bytes ( literal : & [ u8 ] ) -> Option < f64 > {
10
37
parse_inner ( trim_slice ( literal, |b| b. is_ascii_whitespace ( ) ) )
11
38
}
@@ -28,12 +55,16 @@ fn parse_inner(literal: &[u8]) -> Option<f64> {
28
55
use lexical_parse_float:: {
29
56
format:: PYTHON3_LITERAL , FromLexicalWithOptions , NumberFormatBuilder , Options ,
30
57
} ;
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
+
31
63
// lexical-core's format::PYTHON_STRING is inaccurate
32
64
const PYTHON_STRING : u128 = NumberFormatBuilder :: rebuild ( PYTHON3_LITERAL )
33
65
. no_special ( false )
34
- . consecutive_digit_separator ( false )
35
66
. 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 ( )
37
68
}
38
69
39
70
pub fn is_integer ( v : f64 ) -> bool {
0 commit comments