1 //! Low-level API generator.
2 //!
3 //! Uses either the imprecise or the precise algorithm.
4 
5 use crate::lib::slice;
6 use crate::util::*;
7 
8 // Select the back-end
9 cfg_if! {
10 if #[cfg(feature = "correct")] {
11     use super::algorithm::correct as algorithm;
12 } else {
13     use super::algorithm::incorrect as algorithm;
14 }}  // cfg_if
15 
16 // TRAITS
17 
18 /// Trait to define parsing of a string to float.
19 trait StringToFloat: Float {
20     /// Serialize string to float, favoring correctness.
default(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat) -> ParseResult<(Self, *const u8)>21     fn default(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat) -> ParseResult<(Self, *const u8)>;
22 }
23 
24 impl StringToFloat for f32 {
25     perftools_inline_always!{
26     fn default(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat)
27         -> ParseResult<(f32, *const u8)>
28     {
29         algorithm::atof(bytes, radix, lossy, sign, format)
30     }}
31 }
32 
33 impl StringToFloat for f64 {
34     perftools_inline_always!{
35     fn default(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat)
36         -> ParseResult<(f64, *const u8)>
37     {
38         algorithm::atod(bytes, radix, lossy, sign, format)
39     }}
40 }
41 
42 // SPECIAL
43 // Utilities to filter special values.
44 
45 // Convert slice to iterator without digit separators.
46 perftools_inline!{
47 fn to_iter<'a>(bytes: &'a [u8], _: u8) -> slice::Iter<'a, u8> {
48     bytes.iter()
49 }}
50 
51 // Convert slice to iterator with digit separators.
52 perftools_inline!{
53 #[cfg(feature = "format")]
54 fn to_iter_s<'a>(bytes: &'a [u8], digit_separator: u8) -> SkipValueIterator<'a, u8> {
55     SkipValueIterator::new(bytes, digit_separator)
56 }}
57 
58 // PARSER
59 
60 // Parse infinity from string.
61 perftools_inline!{
62 fn parse_infinity<'a, ToIter, StartsWith, Iter, F>(
63     bytes: &'a [u8],
64     radix: u32,
65     lossy: bool,
66     sign: Sign,
67     format: NumberFormat,
68     to_iter: ToIter,
69     starts_with: StartsWith
70 )
71     -> ParseResult<(F, *const u8)>
72     where F: StringToFloat,
73           ToIter: Fn(&'a [u8], u8) -> Iter,
74           Iter: AsPtrIterator<'a, u8>,
75           StartsWith: Fn(Iter, slice::Iter<'a, u8>) -> (bool, Iter)
76 {
77     let infinity = get_infinity_string();
78     let inf = get_inf_string();
79     if let (true, iter) = starts_with(to_iter(bytes, format.digit_separator()), infinity.iter()) {
80         Ok((F::INFINITY, iter.as_ptr()))
81     } else if let (true, iter) = starts_with(to_iter(bytes, format.digit_separator()), inf.iter()) {
82         Ok((F::INFINITY, iter.as_ptr()))
83     } else {
84         // Not infinity, may be valid with a different radix.
85         if cfg!(feature = "radix"){
86             F::default(bytes, radix, lossy, sign, format)
87         } else {
88             Err((ErrorCode::InvalidDigit, bytes.as_ptr()))
89         }
90     }
91 }}
92 
93 // Parse NaN from string.
94 perftools_inline!{
95 fn parse_nan<'a, ToIter, StartsWith, Iter, F>(
96     bytes: &'a [u8],
97     radix: u32,
98     lossy: bool,
99     sign: Sign,
100     format: NumberFormat,
101     to_iter: ToIter,
102     starts_with: StartsWith
103 )
104 -> ParseResult<(F, *const u8)>
105     where F: StringToFloat,
106           ToIter: Fn(&'a [u8], u8) -> Iter,
107           Iter: AsPtrIterator<'a, u8>,
108           StartsWith: Fn(Iter, slice::Iter<'a, u8>) -> (bool, Iter)
109 {
110     let nan = get_nan_string();
111     if let (true, iter) = starts_with(to_iter(bytes, format.digit_separator()), nan.iter()) {
112         Ok((F::NAN, iter.as_ptr()))
113     } else {
114         // Not NaN, may be valid with a different radix.
115         if cfg!(feature = "radix"){
116             F::default(bytes, radix, lossy, sign, format)
117         } else {
118             Err((ErrorCode::InvalidDigit, bytes.as_ptr()))
119         }
120     }
121 }}
122 
123 // ATOF/ATOD
124 
125 // Parse special or float values with the standard format.
126 // Special values are allowed, the match is case-insensitive,
127 // and no digit separators are allowed.
128 perftools_inline!{
129 fn parse_float_standard<F: StringToFloat>(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat)
130     -> ParseResult<(F, *const u8)>
131 {
132     // Use predictive parsing to filter special cases. This leads to
133     // dramatic performance gains.
134     let starts_with = case_insensitive_starts_with_iter;
135     match index!(bytes[0]) {
136         b'i' | b'I' => parse_infinity(bytes, radix, lossy, sign, format, to_iter, starts_with),
137         b'N' | b'n' => parse_nan(bytes, radix, lossy, sign, format, to_iter, starts_with),
138         _           => F::default(bytes, radix, lossy, sign, format),
139     }
140 }}
141 
142 // Parse special or float values.
143 // Special values are allowed, the match is case-sensitive,
144 // and digit separators are allowed.
145 perftools_inline!{
146 #[cfg(feature = "format")]
147 fn parse_float_cs<F: StringToFloat>(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat)
148     -> ParseResult<(F, *const u8)>
149 {
150     let digit_separator = format.digit_separator();
151     let starts_with = starts_with_iter;
152     match SkipValueIterator::new(bytes, digit_separator).next()  {
153         Some(&b'i') | Some(&b'I')   => parse_infinity(bytes, radix, lossy, sign, format, to_iter_s, starts_with),
154         Some(&b'n') | Some(&b'N')   => parse_nan(bytes, radix, lossy, sign, format, to_iter_s, starts_with),
155         _                           => F::default(bytes, radix, lossy, sign, format),
156     }
157 }}
158 
159 // Parse special or float values.
160 // Special values are allowed, the match is case-sensitive,
161 // and no digit separators are allowed.
162 perftools_inline!{
163 #[cfg(feature = "format")]
164 fn parse_float_c<F: StringToFloat>(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat)
165     -> ParseResult<(F, *const u8)>
166 {
167     // Use predictive parsing to filter special cases. This leads to
168     // dramatic performance gains.
169     let starts_with = starts_with_iter;
170     match index!(bytes[0]) {
171         b'i' | b'I' => parse_infinity(bytes, radix, lossy, sign, format, to_iter, starts_with),
172         b'N' | b'n' => parse_nan(bytes, radix, lossy, sign, format, to_iter, starts_with),
173         _           => F::default(bytes, radix, lossy, sign, format),
174     }
175 }}
176 
177 // Parse special or float values.
178 // Special values are allowed, the match is case-insensitive,
179 // and digit separators are allowed.
180 perftools_inline!{
181 #[cfg(feature = "format")]
182 fn parse_float_s<F: StringToFloat>(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat)
183     -> ParseResult<(F, *const u8)>
184 {
185     let digit_separator = format.digit_separator();
186     let starts_with = case_insensitive_starts_with_iter;
187     match SkipValueIterator::new(bytes, digit_separator).next()  {
188         Some(&b'i') | Some(&b'I')   => parse_infinity(bytes, radix, lossy, sign, format, to_iter_s, starts_with),
189         Some(&b'n') | Some(&b'N')   => parse_nan(bytes, radix, lossy, sign, format, to_iter_s, starts_with),
190         _                           => F::default(bytes, radix, lossy, sign, format),
191     }
192 }}
193 
194 // Parse special or float values with the default formatter.
195 perftools_inline!{
196 #[cfg(not(feature = "format"))]
197 fn parse_float<F: StringToFloat>(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat)
198     -> ParseResult<(F, *const u8)>
199 {
200     parse_float_standard(bytes, radix, lossy, sign, format)
201 }}
202 
203 // Parse special or float values with the default formatter.
204 perftools_inline!{
205 #[cfg(feature = "format")]
206 fn parse_float<F: StringToFloat>(bytes: &[u8], radix: u32, lossy: bool, sign: Sign, format: NumberFormat)
207     -> ParseResult<(F, *const u8)>
208 {
209     // Need to consider 3 possibilities:
210     //  1). No special values are allowed.
211     //  2). Special values are case-sensitive.
212     //  3). Digit separators are allowed in the special.
213     let no_special = format.no_special();
214     let case = format.case_sensitive_special();
215     let has_sep = format.special_digit_separator();
216     match (no_special, case, has_sep) {
217         (true, _, _)            => F::default(bytes, radix, lossy, sign, format),
218         (false, true, true)     => parse_float_cs(bytes, radix, lossy, sign, format),
219         (false, false, true)    => parse_float_s(bytes, radix, lossy, sign, format),
220         (false, true, false)    => parse_float_c(bytes, radix, lossy, sign, format),
221         (false, false, false)   => parse_float_standard(bytes, radix, lossy, sign, format),
222     }
223 }}
224 
225 // Validate sign byte is valid.
226 perftools_inline!{
227 #[cfg(not(feature = "format"))]
228 fn validate_sign(_: &[u8], _: &[u8], _: Sign, _: NumberFormat)
229     -> ParseResult<()>
230 {
231     Ok(())
232 }}
233 
234 // Validate sign byte is valid.
235 perftools_inline!{
236 #[cfg(feature = "format")]
237 fn validate_sign(bytes: &[u8], digits: &[u8], sign: Sign, format: NumberFormat)
238     -> ParseResult<()>
239 {
240     let has_sign = bytes.as_ptr() != digits.as_ptr();
241     if format.no_positive_mantissa_sign() && has_sign && sign == Sign::Positive {
242         Err((ErrorCode::InvalidPositiveMantissaSign, bytes.as_ptr()))
243     } else if format.required_mantissa_sign() && !has_sign {
244         Err((ErrorCode::MissingMantissaSign, bytes.as_ptr()))
245     } else {
246         Ok(())
247     }
248 }}
249 
250 // Convert float to signed representation.
251 perftools_inline!{
252 fn to_signed<F: StringToFloat>(float: F, sign: Sign) -> F
253 {
254     match sign {
255         Sign::Positive => float,
256         Sign::Negative => -float
257     }
258 }}
259 
260 // Standalone atof processor.
261 perftools_inline!{
262 fn atof<F: StringToFloat>(bytes: &[u8], radix: u32, lossy: bool, format: NumberFormat)
263     -> ParseResult<(F, *const u8)>
264 {
265     let (sign, digits) = parse_sign::<F>(bytes, format);
266     if digits.is_empty() {
267         return Err((ErrorCode::Empty, digits.as_ptr()));
268     }
269     let (float, ptr): (F, *const u8) = parse_float(digits, radix, lossy, sign, format)?;
270     validate_sign(bytes, digits, sign, format)?;
271 
272     Ok((to_signed(float, sign), ptr))
273 }}
274 
275 perftools_inline!{
276 fn atof_lossy<F: StringToFloat>(bytes: &[u8], radix: u32)
277     -> Result<(F, usize)>
278 {
279     let index = | ptr | distance(bytes.as_ptr(), ptr);
280     match atof::<F>(bytes, radix, true, NumberFormat::standard().unwrap()) {
281         Ok((value, ptr)) => Ok((value, index(ptr))),
282         Err((code, ptr)) => Err((code, index(ptr)).into()),
283     }
284 }}
285 
286 perftools_inline!{
287 fn atof_nonlossy<F: StringToFloat>(bytes: &[u8], radix: u32)
288     -> Result<(F, usize)>
289 {
290     let index = | ptr | distance(bytes.as_ptr(), ptr);
291     match atof::<F>(bytes, radix, false, NumberFormat::standard().unwrap()) {
292         Ok((value, ptr)) => Ok((value, index(ptr))),
293         Err((code, ptr)) => Err((code, index(ptr)).into()),
294     }
295 }}
296 
297 perftools_inline!{
298 #[cfg(feature = "format")]
299 fn atof_format<F: StringToFloat>(bytes: &[u8], radix: u32, format: NumberFormat)
300     -> Result<(F, usize)>
301 {
302     let index = | ptr | distance(bytes.as_ptr(), ptr);
303     match atof::<F>(bytes, radix, false, format) {
304         Ok((value, ptr)) => Ok((value, index(ptr))),
305         Err((code, ptr)) => Err((code, index(ptr)).into()),
306     }
307 }}
308 
309 perftools_inline!{
310 #[cfg(feature = "format")]
311 fn atof_lossy_format<F: StringToFloat>(bytes: &[u8], radix: u32, format: NumberFormat)
312     -> Result<(F, usize)>
313 {
314     let index = | ptr | distance(bytes.as_ptr(), ptr);
315     match atof::<F>(bytes, radix, true, format) {
316         Ok((value, ptr)) => Ok((value, index(ptr))),
317         Err((code, ptr)) => Err((code, index(ptr)).into()),
318     }
319 }}
320 
321 // FROM LEXICAL
322 // ------------
323 
324 from_lexical!(atof_nonlossy, f32);
325 from_lexical!(atof_nonlossy, f64);
326 from_lexical_lossy!(atof_lossy, f32);
327 from_lexical_lossy!(atof_lossy, f64);
328 
329 cfg_if!{
330 if #[cfg(feature = "format")] {
331     from_lexical_format!(atof_format, f32);
332     from_lexical_format!(atof_format, f64);
333     from_lexical_lossy_format!(atof_lossy_format, f32);
334     from_lexical_lossy_format!(atof_lossy_format, f64);
335 }}
336 
337 // TESTS
338 // -----
339 
340 #[cfg(test)]
341 mod tests {
342     use crate::util::*;
343 
344     use approx::assert_relative_eq;
345     #[cfg(all(feature = "std", feature = "property_tests"))]
346     use proptest::{proptest, prop_assert_eq, prop_assert};
347 
348     #[test]
f32_decimal_test()349     fn f32_decimal_test() {
350         // integer test
351         assert_f32_eq!(0.0, f32::from_lexical(b"0").unwrap());
352         assert_f32_eq!(1.0, f32::from_lexical(b"1").unwrap());
353         assert_f32_eq!(12.0, f32::from_lexical(b"12").unwrap());
354         assert_f32_eq!(123.0, f32::from_lexical(b"123").unwrap());
355         assert_f32_eq!(1234.0, f32::from_lexical(b"1234").unwrap());
356         assert_f32_eq!(12345.0, f32::from_lexical(b"12345").unwrap());
357         assert_f32_eq!(123456.0, f32::from_lexical(b"123456").unwrap());
358         assert_f32_eq!(1234567.0, f32::from_lexical(b"1234567").unwrap());
359         assert_f32_eq!(12345678.0, f32::from_lexical(b"12345678").unwrap());
360 
361          // No fraction after decimal point test
362         assert_f32_eq!(1.0, f32::from_lexical(b"1.").unwrap());
363         assert_f32_eq!(12.0, f32::from_lexical(b"12.").unwrap());
364         assert_f32_eq!(1234567.0, f32::from_lexical(b"1234567.").unwrap());
365 
366         // No integer before decimal point test
367         assert_f32_eq!(0.1, f32::from_lexical(b".1").unwrap());
368         assert_f32_eq!(0.12, f32::from_lexical(b".12").unwrap());
369         assert_f32_eq!(0.1234567, f32::from_lexical(b".1234567").unwrap());
370 
371         // decimal test
372         assert_f32_eq!(123.1, f32::from_lexical(b"123.1").unwrap());
373         assert_f32_eq!(123.12, f32::from_lexical(b"123.12").unwrap());
374         assert_f32_eq!(123.123, f32::from_lexical(b"123.123").unwrap());
375         assert_f32_eq!(123.1234, f32::from_lexical(b"123.1234").unwrap());
376         assert_f32_eq!(123.12345, f32::from_lexical(b"123.12345").unwrap());
377 
378         // rounding test
379         assert_f32_eq!(123456790.0, f32::from_lexical(b"123456789").unwrap());
380         assert_f32_eq!(123456790.0, f32::from_lexical(b"123456789.1").unwrap());
381         assert_f32_eq!(123456790.0, f32::from_lexical(b"123456789.12").unwrap());
382         assert_f32_eq!(123456790.0, f32::from_lexical(b"123456789.123").unwrap());
383         assert_f32_eq!(123456790.0, f32::from_lexical(b"123456789.1234").unwrap());
384         assert_f32_eq!(123456790.0, f32::from_lexical(b"123456789.12345").unwrap());
385 
386         // exponent test
387         assert_f32_eq!(123456789.12345, f32::from_lexical(b"1.2345678912345e8").unwrap());
388         assert_f32_eq!(123450000.0, f32::from_lexical(b"1.2345e+8").unwrap());
389         assert_f32_eq!(1.2345e+11, f32::from_lexical(b"1.2345e+11").unwrap());
390         assert_f32_eq!(1.2345e+11, f32::from_lexical(b"123450000000").unwrap());
391         assert_f32_eq!(1.2345e+38, f32::from_lexical(b"1.2345e+38").unwrap());
392         assert_f32_eq!(1.2345e+38, f32::from_lexical(b"123450000000000000000000000000000000000").unwrap());
393         assert_f32_eq!(1.2345e-8, f32::from_lexical(b"1.2345e-8").unwrap());
394         assert_f32_eq!(1.2345e-8, f32::from_lexical(b"0.000000012345").unwrap());
395         assert_f32_eq!(1.2345e-38, f32::from_lexical(b"1.2345e-38").unwrap());
396         assert_f32_eq!(1.2345e-38, f32::from_lexical(b"0.000000000000000000000000000000000000012345").unwrap());
397 
398         assert!(f32::from_lexical(b"NaN").unwrap().is_nan());
399         assert!(f32::from_lexical(b"nan").unwrap().is_nan());
400         assert!(f32::from_lexical(b"NAN").unwrap().is_nan());
401         assert!(f32::from_lexical(b"inf").unwrap().is_infinite());
402         assert!(f32::from_lexical(b"INF").unwrap().is_infinite());
403         assert!(f32::from_lexical(b"+inf").unwrap().is_infinite());
404         assert!(f32::from_lexical(b"-inf").unwrap().is_infinite());
405 
406         // Check various expected failures.
407         assert_eq!(Err(ErrorCode::Empty.into()), f32::from_lexical(b""));
408         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f32::from_lexical(b"e"));
409         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f32::from_lexical(b"E"));
410         assert_eq!(Err(ErrorCode::EmptyMantissa.into()), f32::from_lexical(b".e1"));
411         assert_eq!(Err(ErrorCode::EmptyMantissa.into()), f32::from_lexical(b".e-1"));
412         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f32::from_lexical(b"e1"));
413         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f32::from_lexical(b"e-1"));
414         assert_eq!(Err((ErrorCode::Empty, 1).into()), f32::from_lexical(b"+"));
415         assert_eq!(Err((ErrorCode::Empty, 1).into()), f32::from_lexical(b"-"));
416 
417         // Bug fix for Issue #8
418         assert_eq!(Ok(5.002868148396374), f32::from_lexical(b"5.002868148396374"));
419     }
420 
421     #[cfg(feature = "radix")]
422     #[test]
f32_radix_test()423     fn f32_radix_test() {
424         assert_f32_eq!(1234.0, f32::from_lexical_radix(b"YA", 36).unwrap());
425         assert_f32_eq!(1234.0, f32::from_lexical_lossy_radix(b"YA", 36).unwrap());
426     }
427 
428     #[test]
f64_decimal_test()429     fn f64_decimal_test() {
430         // integer test
431         assert_f64_eq!(0.0, f64::from_lexical(b"0").unwrap());
432         assert_f64_eq!(1.0, f64::from_lexical(b"1").unwrap());
433         assert_f64_eq!(12.0, f64::from_lexical(b"12").unwrap());
434         assert_f64_eq!(123.0, f64::from_lexical(b"123").unwrap());
435         assert_f64_eq!(1234.0, f64::from_lexical(b"1234").unwrap());
436         assert_f64_eq!(12345.0, f64::from_lexical(b"12345").unwrap());
437         assert_f64_eq!(123456.0, f64::from_lexical(b"123456").unwrap());
438         assert_f64_eq!(1234567.0, f64::from_lexical(b"1234567").unwrap());
439         assert_f64_eq!(12345678.0, f64::from_lexical(b"12345678").unwrap());
440 
441         // No fraction after decimal point test
442         assert_f64_eq!(1.0, f64::from_lexical(b"1.").unwrap());
443         assert_f64_eq!(12.0, f64::from_lexical(b"12.").unwrap());
444         assert_f64_eq!(1234567.0, f64::from_lexical(b"1234567.").unwrap());
445 
446         // No integer before decimal point test
447         assert_f64_eq!(0.1, f64::from_lexical(b".1").unwrap());
448         assert_f64_eq!(0.12, f64::from_lexical(b".12").unwrap());
449         assert_f64_eq!(0.1234567, f64::from_lexical(b".1234567").unwrap());
450 
451         // decimal test
452         assert_f64_eq!(123456789.0, f64::from_lexical(b"123456789").unwrap());
453         assert_f64_eq!(123456789.1, f64::from_lexical(b"123456789.1").unwrap());
454         assert_f64_eq!(123456789.12, f64::from_lexical(b"123456789.12").unwrap());
455         assert_f64_eq!(123456789.123, f64::from_lexical(b"123456789.123").unwrap());
456         assert_f64_eq!(123456789.1234, f64::from_lexical(b"123456789.1234").unwrap());
457         assert_f64_eq!(123456789.12345, f64::from_lexical(b"123456789.12345").unwrap());
458         assert_f64_eq!(123456789.123456, f64::from_lexical(b"123456789.123456").unwrap());
459         assert_f64_eq!(123456789.1234567, f64::from_lexical(b"123456789.1234567").unwrap());
460         assert_f64_eq!(123456789.12345678, f64::from_lexical(b"123456789.12345678").unwrap());
461 
462         // rounding test
463         assert_f64_eq!(123456789.12345679, f64::from_lexical(b"123456789.123456789").unwrap());
464         assert_f64_eq!(123456789.12345679, f64::from_lexical(b"123456789.1234567890").unwrap());
465         assert_f64_eq!(123456789.12345679, f64::from_lexical(b"123456789.123456789012").unwrap());
466         assert_f64_eq!(123456789.12345679, f64::from_lexical(b"123456789.1234567890123").unwrap());
467         assert_f64_eq!(123456789.12345679, f64::from_lexical(b"123456789.12345678901234").unwrap());
468 
469         // exponent test
470         assert_f64_eq!(123456789.12345, f64::from_lexical(b"1.2345678912345e8").unwrap());
471         assert_f64_eq!(123450000.0, f64::from_lexical(b"1.2345e+8").unwrap());
472         assert_f64_eq!(1.2345e+11, f64::from_lexical(b"123450000000").unwrap());
473         assert_f64_eq!(1.2345e+11, f64::from_lexical(b"1.2345e+11").unwrap());
474         assert_f64_eq!(1.2345e+38, f64::from_lexical(b"1.2345e+38").unwrap());
475         assert_f64_eq!(1.2345e+38, f64::from_lexical(b"123450000000000000000000000000000000000").unwrap());
476         assert_f64_eq!(1.2345e+308, f64::from_lexical(b"1.2345e+308").unwrap());
477         assert_f64_eq!(1.2345e+308, f64::from_lexical(b"123450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap());
478         assert_f64_eq!(0.000000012345, f64::from_lexical(b"1.2345e-8").unwrap());
479         assert_f64_eq!(1.2345e-8, f64::from_lexical(b"0.000000012345").unwrap());
480         assert_f64_eq!(1.2345e-38, f64::from_lexical(b"1.2345e-38").unwrap());
481         assert_f64_eq!(1.2345e-38, f64::from_lexical(b"0.000000000000000000000000000000000000012345").unwrap());
482 
483         // denormalized (try extremely low values)
484         assert_f64_eq!(1.2345e-308, f64::from_lexical(b"1.2345e-308").unwrap());
485         // These next 3 tests fail on arm-unknown-linux-gnueabi with the
486         // incorrect parser.
487         #[cfg(all(not(feature = "correct"), not(target_arch = "arm")))]
488         assert_eq!(Ok(5e-322), f64::from_lexical(b"5e-322"));
489         #[cfg(all(not(feature = "correct"), not(target_arch = "arm")))]
490         assert_eq!(Ok(5e-323), f64::from_lexical(b"5e-323"));
491         #[cfg(all(not(feature = "correct"), not(target_arch = "arm")))]
492         assert_eq!(Ok(5e-324), f64::from_lexical(b"5e-324"));
493         // due to issues in how the data is parsed, manually extracting
494         // non-exponents of 1.<e-299 is prone to error
495         // test the limit of our ability
496         // We tend to get relative errors of 1e-16, even at super low values.
497         assert_f64_eq!(1.2345e-299, f64::from_lexical(b"0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012345").unwrap(), epsilon=1e-314);
498 
499         // Keep pushing from -300 to -324
500         assert_f64_eq!(1.2345e-300, f64::from_lexical(b"0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012345").unwrap(), epsilon=1e-315);
501 
502         // These next 3 tests fail on arm-unknown-linux-gnueabi with the
503         // incorrect parser.
504         #[cfg(all(not(feature = "correct"), not(target_arch = "arm")))]
505         assert_f64_eq!(1.2345e-310, f64::from_lexical(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012345").unwrap(), epsilon=5e-324);
506         #[cfg(all(not(feature = "correct"), not(target_arch = "arm")))]
507         assert_f64_eq!(1.2345e-320, f64::from_lexical(b"0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012345").unwrap(), epsilon=5e-324);
508         #[cfg(all(not(feature = "correct"), not(target_arch = "arm")))]
509         assert_f64_eq!(1.2345e-321, f64::from_lexical(b"0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012345").unwrap(), epsilon=5e-324);
510         #[cfg(all(not(feature = "correct"), not(target_arch = "arm")))]
511         assert_f64_eq!(1.24e-322, f64::from_lexical(b"0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124").unwrap(), epsilon=5e-324);
512         #[cfg(all(not(feature = "correct"), not(target_arch = "arm")))]
513         assert_eq!(Ok(1e-323), f64::from_lexical(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"));
514         #[cfg(all(not(feature = "correct"), not(target_arch = "arm")))]
515         assert_eq!(Ok(5e-324), f64::from_lexical(b"0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005"));
516 
517         assert!(f64::from_lexical(b"NaN").unwrap().is_nan());
518         assert!(f64::from_lexical(b"nan").unwrap().is_nan());
519         assert!(f64::from_lexical(b"NAN").unwrap().is_nan());
520         assert!(f64::from_lexical(b"inf").unwrap().is_infinite());
521         assert!(f64::from_lexical(b"INF").unwrap().is_infinite());
522         assert!(f64::from_lexical(b"+inf").unwrap().is_infinite());
523         assert!(f64::from_lexical(b"-inf").unwrap().is_infinite());
524 
525         // Check various expected failures.
526         assert_eq!(Err(ErrorCode::Empty.into()), f64::from_lexical(b""));
527         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f64::from_lexical(b"e"));
528         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f64::from_lexical(b"E"));
529         assert_eq!(Err(ErrorCode::EmptyMantissa.into()), f64::from_lexical(b".e1"));
530         assert_eq!(Err(ErrorCode::EmptyMantissa.into()), f64::from_lexical(b".e-1"));
531         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f64::from_lexical(b"e1"));
532         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f64::from_lexical(b"e-1"));
533 
534         // Check various reports from a fuzzer.
535         assert_eq!(Err((ErrorCode::EmptyExponent, 2).into()), f64::from_lexical(b"0e"));
536         assert_eq!(Err((ErrorCode::EmptyExponent, 4).into()), f64::from_lexical(b"0.0e"));
537         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f64::from_lexical(b".E"));
538         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f64::from_lexical(b".e"));
539         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f64::from_lexical(b"E2252525225"));
540         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f64::from_lexical(b"e2252525225"));
541         assert_eq!(Ok(f64::INFINITY), f64::from_lexical(b"2E200000000000"));
542 
543         // Add various unittests from proptests.
544         assert_eq!(Err((ErrorCode::EmptyExponent, 2).into()), f64::from_lexical(b"0e"));
545         assert_eq!(Err((ErrorCode::EmptyMantissa, 0).into()), f64::from_lexical(b"."));
546         assert_eq!(Err((ErrorCode::EmptyMantissa, 1).into()), f64::from_lexical(b"+."));
547         assert_eq!(Err((ErrorCode::EmptyMantissa, 1).into()), f64::from_lexical(b"-."));
548         assert_eq!(Err((ErrorCode::Empty, 1).into()), f64::from_lexical(b"+"));
549         assert_eq!(Err((ErrorCode::Empty, 1).into()), f64::from_lexical(b"-"));
550 
551         // Bug fix for Issue #8
552         assert_eq!(Ok(5.002868148396374), f64::from_lexical(b"5.002868148396374"));
553     }
554 
555     #[test]
556     #[should_panic]
limit_test()557     fn limit_test() {
558         assert_relative_eq!(1.2345e-320, 0.0, epsilon=5e-324);
559     }
560 
561     #[cfg(feature = "radix")]
562     #[test]
f64_radix_test()563     fn f64_radix_test() {
564         assert_f64_eq!(1234.0, f64::from_lexical_radix(b"YA", 36).unwrap());
565         assert_f64_eq!(1234.0, f64::from_lexical_lossy_radix(b"YA", 36).unwrap());
566     }
567 
568     #[test]
f32_lossy_decimal_test()569     fn f32_lossy_decimal_test() {
570         assert_eq!(Err(ErrorCode::EmptyMantissa.into()), f32::from_lexical_lossy(b"."));
571         assert_eq!(Err(ErrorCode::Empty.into()), f32::from_lexical_lossy(b""));
572         assert_eq!(Ok(0.0), f32::from_lexical_lossy(b"0.0"));
573         assert_eq!(Err((ErrorCode::InvalidDigit, 1).into()), f32::from_lexical_lossy(b"1a"));
574 
575         // Bug fix for Issue #8
576         assert_eq!(Ok(5.002868148396374), f32::from_lexical_lossy(b"5.002868148396374"));
577     }
578 
579     #[test]
f64_lossy_decimal_test()580     fn f64_lossy_decimal_test() {
581         assert_eq!(Err(ErrorCode::EmptyMantissa.into()), f64::from_lexical_lossy(b"."));
582         assert_eq!(Err(ErrorCode::Empty.into()), f64::from_lexical_lossy(b""));
583         assert_eq!(Ok(0.0), f64::from_lexical_lossy(b"0.0"));
584         assert_eq!(Err((ErrorCode::InvalidDigit, 1).into()), f64::from_lexical_lossy(b"1a"));
585 
586         // Bug fix for Issue #8
587         assert_eq!(Ok(5.002868148396374), f64::from_lexical_lossy(b"5.002868148396374"));
588     }
589 
590     #[test]
591     #[cfg(feature = "format")]
f64_special_test()592     fn f64_special_test() {
593         //  Comments match (no_special, case_sensitive, has_sep)
594         let f1 = NumberFormat::standard().unwrap();         // false, false, false
595         let f2 = NumberFormat::ignore(b'_').unwrap();       // false, false, true
596         let f3 = f1 | NumberFormat::NO_SPECIAL;             // true, _, _
597         let f4 = f1 | NumberFormat::CASE_SENSITIVE_SPECIAL; // false, true, false
598         let f5 = f2 | NumberFormat::CASE_SENSITIVE_SPECIAL; // false, true, true
599 
600         // Easy NaN
601         assert!(f64::from_lexical_format(b"NaN", f1).unwrap().is_nan());
602         assert!(f64::from_lexical_format(b"NaN", f2).unwrap().is_nan());
603         assert!(f64::from_lexical_format(b"NaN", f3).is_err());
604         assert!(f64::from_lexical_format(b"NaN", f4).unwrap().is_nan());
605         assert!(f64::from_lexical_format(b"NaN", f5).unwrap().is_nan());
606 
607         // Case-sensitive NaN.
608         assert!(f64::from_lexical_format(b"nan", f1).unwrap().is_nan());
609         assert!(f64::from_lexical_format(b"nan", f2).unwrap().is_nan());
610         assert!(f64::from_lexical_format(b"nan", f3).is_err());
611         assert!(f64::from_lexical_format(b"nan", f4).is_err());
612         assert!(f64::from_lexical_format(b"nan", f5).is_err());
613 
614         // Digit-separator NaN.
615         assert!(f64::from_lexical_format(b"N_aN", f1).is_err());
616         assert!(f64::from_lexical_format(b"N_aN", f2).unwrap().is_nan());
617         assert!(f64::from_lexical_format(b"N_aN", f3).is_err());
618         assert!(f64::from_lexical_format(b"N_aN", f4).is_err());
619         assert!(f64::from_lexical_format(b"N_aN", f5).unwrap().is_nan());
620 
621         // Digit-separator + case-sensitive NaN.
622         assert!(f64::from_lexical_format(b"n_an", f1).is_err());
623         assert!(f64::from_lexical_format(b"n_an", f2).unwrap().is_nan());
624         assert!(f64::from_lexical_format(b"n_an", f3).is_err());
625         assert!(f64::from_lexical_format(b"n_an", f4).is_err());
626         assert!(f64::from_lexical_format(b"n_an", f5).is_err());
627     }
628 
629     #[test]
630     #[cfg(feature = "format")]
f64_required_integer_digits_test()631     fn f64_required_integer_digits_test() {
632         let format = NumberFormat::REQUIRED_INTEGER_DIGITS;
633         assert!(f64::from_lexical_format(b"+3.0", format).is_ok());
634         assert!(f64::from_lexical_format(b"3.0", format).is_ok());
635         assert!(f64::from_lexical_format(b".0", format).is_err());
636     }
637 
638     #[test]
639     #[cfg(feature = "format")]
f64_required_fraction_digits_test()640     fn f64_required_fraction_digits_test() {
641         let format = NumberFormat::REQUIRED_FRACTION_DIGITS;
642         assert!(f64::from_lexical_format(b"+3.0", format).is_ok());
643         assert!(f64::from_lexical_format(b"3.0", format).is_ok());
644         assert!(f64::from_lexical_format(b"3.", format).is_err());
645         assert!(f64::from_lexical_format(b"3", format).is_ok());
646     }
647 
648     #[test]
649     #[cfg(feature = "format")]
f64_required_digits_test()650     fn f64_required_digits_test() {
651         let format = NumberFormat::REQUIRED_DIGITS;
652         assert!(f64::from_lexical_format(b"+3.0", format).is_ok());
653         assert!(f64::from_lexical_format(b"3.0", format).is_ok());
654         assert!(f64::from_lexical_format(b"3.", format).is_err());
655         assert!(f64::from_lexical_format(b"3", format).is_ok());
656         assert!(f64::from_lexical_format(b".0", format).is_err());
657     }
658 
659     #[test]
660     #[cfg(feature = "format")]
f64_no_positive_mantissa_sign_test()661     fn f64_no_positive_mantissa_sign_test() {
662         let format = NumberFormat::NO_POSITIVE_MANTISSA_SIGN;
663         assert!(f64::from_lexical_format(b"+3.0", format).is_err());
664         assert!(f64::from_lexical_format(b"-3.0", format).is_ok());
665         assert!(f64::from_lexical_format(b"3.0", format).is_ok());
666     }
667 
668     #[test]
669     #[cfg(feature = "format")]
f64_required_mantissa_sign_test()670     fn f64_required_mantissa_sign_test() {
671         let format = NumberFormat::REQUIRED_MANTISSA_SIGN;
672         assert!(f64::from_lexical_format(b"+3.0", format).is_ok());
673         assert!(f64::from_lexical_format(b"-3.0", format).is_ok());
674         assert!(f64::from_lexical_format(b"3.0", format).is_err());
675     }
676 
677     #[test]
678     #[cfg(feature = "format")]
f64_no_exponent_notation_test()679     fn f64_no_exponent_notation_test() {
680         let format = NumberFormat::NO_EXPONENT_NOTATION;
681         assert!(f64::from_lexical_format(b"+3.0e7", format).is_err());
682         assert!(f64::from_lexical_format(b"+3.0e-7", format).is_err());
683         assert!(f64::from_lexical_format(b"+3e", format).is_err());
684         assert!(f64::from_lexical_format(b"+3e-", format).is_err());
685         assert!(f64::from_lexical_format(b"+3.0", format).is_ok());
686         assert!(f64::from_lexical_format(b"+3", format).is_ok());
687     }
688 
689     #[test]
690     #[cfg(feature = "format")]
f64_optional_exponent_test()691     fn f64_optional_exponent_test() {
692         let format = NumberFormat::permissive().unwrap();
693         assert!(f64::from_lexical_format(b"+3.0e7", format).is_ok());
694         assert!(f64::from_lexical_format(b"+3.0e-7", format).is_ok());
695         assert!(f64::from_lexical_format(b"+3.0e", format).is_ok());
696         assert!(f64::from_lexical_format(b"+3.0e-", format).is_ok());
697         assert!(f64::from_lexical_format(b"+3.0", format).is_ok());
698     }
699 
700     #[test]
701     #[cfg(feature = "format")]
f64_required_exponent_test()702     fn f64_required_exponent_test() {
703         let format = NumberFormat::REQUIRED_EXPONENT_DIGITS;
704         assert!(f64::from_lexical_format(b"+3.0e7", format).is_ok());
705         assert!(f64::from_lexical_format(b"+3.0e-7", format).is_ok());
706         assert!(f64::from_lexical_format(b"+3.0e", format).is_err());
707         assert!(f64::from_lexical_format(b"+3.0e-", format).is_err());
708         assert!(f64::from_lexical_format(b"+3.0", format).is_ok());
709     }
710 
711     #[test]
712     #[cfg(feature = "format")]
f64_no_positive_exponent_sign_test()713     fn f64_no_positive_exponent_sign_test() {
714         let format = NumberFormat::NO_POSITIVE_EXPONENT_SIGN;
715         assert!(f64::from_lexical_format(b"3.0e7", format).is_ok());
716         assert!(f64::from_lexical_format(b"3.0e+7", format).is_err());
717         assert!(f64::from_lexical_format(b"3.0e-7", format).is_ok());
718     }
719 
720     #[test]
721     #[cfg(feature = "format")]
f64_required_exponent_sign_test()722     fn f64_required_exponent_sign_test() {
723         let format = NumberFormat::REQUIRED_EXPONENT_SIGN;
724         assert!(f64::from_lexical_format(b"3.0e7", format).is_err());
725         assert!(f64::from_lexical_format(b"3.0e+7", format).is_ok());
726         assert!(f64::from_lexical_format(b"3.0e-7", format).is_ok());
727     }
728 
729     #[test]
730     #[cfg(feature = "format")]
f64_no_exponent_without_fraction_test()731     fn f64_no_exponent_without_fraction_test() {
732         let format = NumberFormat::NO_EXPONENT_WITHOUT_FRACTION;
733         assert!(f64::from_lexical_format(b"3.0e7", format).is_ok());
734         assert!(f64::from_lexical_format(b"3.e7", format).is_ok());
735         assert!(f64::from_lexical_format(b"3e7", format).is_err());
736 
737         let format = format | NumberFormat::REQUIRED_FRACTION_DIGITS;
738         assert!(f64::from_lexical_format(b"3.0e7", format).is_ok());
739         assert!(f64::from_lexical_format(b"3.e7", format).is_err());
740         assert!(f64::from_lexical_format(b"3e7", format).is_err());
741     }
742 
743     #[test]
744     #[cfg(feature = "format")]
f64_no_leading_zeros_test()745     fn f64_no_leading_zeros_test() {
746         let format = NumberFormat::NO_FLOAT_LEADING_ZEROS;
747         assert!(f64::from_lexical_format(b"1.0", format).is_ok());
748         assert!(f64::from_lexical_format(b"0.0", format).is_ok());
749         assert!(f64::from_lexical_format(b"01.0", format).is_err());
750         assert!(f64::from_lexical_format(b"10.0", format).is_ok());
751         assert!(f64::from_lexical_format(b"010.0", format).is_err());
752     }
753 
754     #[test]
755     #[cfg(feature = "format")]
f64_integer_internal_digit_separator_test()756     fn f64_integer_internal_digit_separator_test() {
757         let format = NumberFormat::from_separator(b'_') | NumberFormat::INTEGER_INTERNAL_DIGIT_SEPARATOR;
758         assert!(f64::from_lexical_format(b"3_1.0e7", format).is_ok());
759         assert!(f64::from_lexical_format(b"_31.0e7", format).is_err());
760         assert!(f64::from_lexical_format(b"31_.0e7", format).is_err());
761     }
762 
763     #[test]
764     #[cfg(feature = "format")]
f64_fraction_internal_digit_separator_test()765     fn f64_fraction_internal_digit_separator_test() {
766         let format = NumberFormat::from_separator(b'_') | NumberFormat::FRACTION_INTERNAL_DIGIT_SEPARATOR;
767         assert!(f64::from_lexical_format(b"31.0_1e7", format).is_ok());
768         assert!(f64::from_lexical_format(b"31._01e7", format).is_err());
769         assert!(f64::from_lexical_format(b"31.01_e7", format).is_err());
770     }
771 
772     #[test]
773     #[cfg(feature = "format")]
f64_exponent_internal_digit_separator_test()774     fn f64_exponent_internal_digit_separator_test() {
775         let format = NumberFormat::from_separator(b'_') | NumberFormat::EXPONENT_INTERNAL_DIGIT_SEPARATOR;
776         assert!(f64::from_lexical_format(b"31.01e7_1", format).is_ok());
777         assert!(f64::from_lexical_format(b"31.01e_71", format).is_err());
778         assert!(f64::from_lexical_format(b"31.01e71_", format).is_err());
779     }
780 
781     #[test]
782     #[cfg(feature = "format")]
f64_integer_leading_digit_separator_test()783     fn f64_integer_leading_digit_separator_test() {
784         let format = NumberFormat::from_separator(b'_') | NumberFormat::INTEGER_LEADING_DIGIT_SEPARATOR;
785         assert!(f64::from_lexical_format(b"3_1.0e7", format).is_err());
786         assert!(f64::from_lexical_format(b"_31.0e7", format).is_ok());
787         assert!(f64::from_lexical_format(b"31_.0e7", format).is_err());
788     }
789 
790     #[test]
791     #[cfg(feature = "format")]
f64_fraction_leading_digit_separator_test()792     fn f64_fraction_leading_digit_separator_test() {
793         let format = NumberFormat::from_separator(b'_') | NumberFormat::FRACTION_LEADING_DIGIT_SEPARATOR;
794         assert!(f64::from_lexical_format(b"31.0_1e7", format).is_err());
795         assert!(f64::from_lexical_format(b"31._01e7", format).is_ok());
796         assert!(f64::from_lexical_format(b"31.01_e7", format).is_err());
797     }
798 
799     #[test]
800     #[cfg(feature = "format")]
f64_exponent_leading_digit_separator_test()801     fn f64_exponent_leading_digit_separator_test() {
802         let format = NumberFormat::from_separator(b'_') | NumberFormat::EXPONENT_LEADING_DIGIT_SEPARATOR;
803         assert!(f64::from_lexical_format(b"31.01e7_1", format).is_err());
804         assert!(f64::from_lexical_format(b"31.01e_71", format).is_ok());
805         assert!(f64::from_lexical_format(b"31.01e71_", format).is_err());
806     }
807 
808     #[test]
809     #[cfg(feature = "format")]
f64_integer_trailing_digit_separator_test()810     fn f64_integer_trailing_digit_separator_test() {
811         let format = NumberFormat::from_separator(b'_') | NumberFormat::INTEGER_TRAILING_DIGIT_SEPARATOR;
812         assert!(f64::from_lexical_format(b"3_1.0e7", format).is_err());
813         assert!(f64::from_lexical_format(b"_31.0e7", format).is_err());
814         assert!(f64::from_lexical_format(b"31_.0e7", format).is_ok());
815     }
816 
817     #[test]
818     #[cfg(feature = "format")]
f64_fraction_trailing_digit_separator_test()819     fn f64_fraction_trailing_digit_separator_test() {
820         let format = NumberFormat::from_separator(b'_') | NumberFormat::FRACTION_TRAILING_DIGIT_SEPARATOR;
821         assert!(f64::from_lexical_format(b"31.0_1e7", format).is_err());
822         assert!(f64::from_lexical_format(b"31._01e7", format).is_err());
823         assert!(f64::from_lexical_format(b"31.01_e7", format).is_ok());
824     }
825 
826     #[test]
827     #[cfg(feature = "format")]
f64_exponent_trailing_digit_separator_test()828     fn f64_exponent_trailing_digit_separator_test() {
829         let format = NumberFormat::from_separator(b'_') | NumberFormat::EXPONENT_TRAILING_DIGIT_SEPARATOR;
830         assert!(f64::from_lexical_format(b"31.01e7_1", format).is_err());
831         assert!(f64::from_lexical_format(b"31.01e_71", format).is_err());
832         assert!(f64::from_lexical_format(b"31.01e71_", format).is_ok());
833     }
834 
835     #[test]
836     #[cfg(feature = "format")]
f64_integer_consecutive_digit_separator_test()837     fn f64_integer_consecutive_digit_separator_test() {
838         let format = NumberFormat::from_separator(b'_')
839             | NumberFormat::INTEGER_INTERNAL_DIGIT_SEPARATOR
840             | NumberFormat::INTEGER_CONSECUTIVE_DIGIT_SEPARATOR;
841         assert!(f64::from_lexical_format(b"3__1.0e7", format).is_ok());
842         assert!(f64::from_lexical_format(b"_31.0e7", format).is_err());
843         assert!(f64::from_lexical_format(b"31_.0e7", format).is_err());
844     }
845 
846     #[test]
847     #[cfg(feature = "format")]
f64_fraction_consecutive_digit_separator_test()848     fn f64_fraction_consecutive_digit_separator_test() {
849         let format = NumberFormat::from_separator(b'_')
850             | NumberFormat::FRACTION_INTERNAL_DIGIT_SEPARATOR
851             | NumberFormat::FRACTION_CONSECUTIVE_DIGIT_SEPARATOR;
852         assert!(f64::from_lexical_format(b"31.0__1e7", format).is_ok());
853         assert!(f64::from_lexical_format(b"31._01e7", format).is_err());
854         assert!(f64::from_lexical_format(b"31.01_e7", format).is_err());
855     }
856 
857     #[test]
858     #[cfg(feature = "format")]
f64_exponent_consecutive_digit_separator_test()859     fn f64_exponent_consecutive_digit_separator_test() {
860         let format = NumberFormat::from_separator(b'_')
861             | NumberFormat::EXPONENT_INTERNAL_DIGIT_SEPARATOR
862             | NumberFormat::EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR;
863         assert!(f64::from_lexical_format(b"31.01e7__1", format).is_ok());
864         assert!(f64::from_lexical_format(b"31.01e_71", format).is_err());
865         assert!(f64::from_lexical_format(b"31.01e71_", format).is_err());
866     }
867 
868     #[test]
869     #[cfg(feature = "format")]
f64_json_exponent_without_dot()870     fn f64_json_exponent_without_dot() {
871         // Tests courtesy of @ijl:
872         //  https://github.com/Alexhuszagh/rust-lexical/issues/24#issuecomment-578153783
873         let format = NumberFormat::JSON;
874         // JSONTestSuite/test_parsing/y_number_0e1.json
875         assert!(f64::from_lexical_format(b"0e1", format).is_ok());
876         // JSONTestSuite/test_parsing/y_number_int_with_exp.json
877         assert!(f64::from_lexical_format(b"20e1", format).is_ok());
878         // JSONTestSuite/test_parsing/y_number_real_capital_e_pos_exp.json
879         assert!(f64::from_lexical_format(b"1E+2", format).is_ok());
880         // JSONTestSuite/test_transform/number_1e-999.json
881         assert!(f64::from_lexical_format(b"1E-999", format).is_ok());
882         // nativejson-benchmark/data/jsonchecker/pass01.json
883         assert!(f64::from_lexical_format(b"23456789012E66", format).is_ok());
884     }
885     #[test]
886     #[cfg(feature = "format")]
f64_json_exponent_requires_digit()887     fn f64_json_exponent_requires_digit() {
888         // Tests courtesy of @ijl:
889         //  https://github.com/Alexhuszagh/rust-lexical/issues/24#issuecomment-578153783
890         let format = NumberFormat::JSON;
891         assert!(f64::from_lexical_format(b"1e", format).is_err());
892         // JSONTestSuite/test_parsing/n_number_9.e+.json
893         assert!(f64::from_lexical_format(b"9.e+", format).is_err());
894         // JSONTestSuite/test_parsing/n_number_2.e-3.json
895         assert!(f64::from_lexical_format(b"2.e-3", format).is_err());
896         // JSONTestSuite/test_parsing/n_number_real_without_fractional_part.json
897         assert!(f64::from_lexical_format(b"1.", format).is_err());
898     }
899 
900     #[test]
901     #[cfg(feature = "format")]
f64_json_no_leading_zero()902     fn f64_json_no_leading_zero() {
903         let format = NumberFormat::JSON;
904         assert!(f64::from_lexical_format(b"12.0", format).is_ok());
905         assert!(f64::from_lexical_format(b"-12.0", format).is_ok());
906         assert!(f64::from_lexical_format(b"012.0", format).is_err());
907         assert!(f64::from_lexical_format(b"-012.0", format).is_err());
908     }
909 
910     #[cfg(all(feature = "std", feature = "property_tests"))]
911     proptest! {
912         #[test]
913         fn f32_invalid_proptest(i in r"[+-]?[0-9]{2}[^\deE]?\.[^\deE]?[0-9]{2}[^\deE]?e[+-]?[0-9]+[^\deE]") {
914             let res = f32::from_lexical(i.as_bytes());
915             prop_assert!(res.is_err());
916             let err = res.err().unwrap();
917             prop_assert_eq!(err.code, ErrorCode::InvalidDigit);
918         }
919 
920         #[test]
921         fn f32_double_sign_proptest(i in r"[+-]{2}[0-9]{2}\.[0-9]{2}e[+-]?[0-9]+") {
922             let res = f32::from_lexical(i.as_bytes());
923             prop_assert!(res.is_err());
924             let err = res.err().unwrap();
925             prop_assert!(err.code == ErrorCode::InvalidDigit || err.code == ErrorCode::EmptyMantissa);
926             prop_assert!(err.index == 0 || err.index == 1);
927         }
928 
929         #[test]
930         fn f32_sign_or_dot_only_proptest(i in r"[+-]?\.?") {
931             let res = f32::from_lexical(i.as_bytes());
932             prop_assert!(res.is_err());
933             let err = res.err().unwrap();
934             prop_assert!(err.code == ErrorCode::Empty || err.code == ErrorCode::EmptyMantissa);
935             prop_assert!(err.index == 0 || err.index == 1);
936         }
937 
938         #[test]
939         fn f32_double_exponent_sign_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]{2}[0-9]+") {
940             let res = f32::from_lexical(i.as_bytes());
941             prop_assert!(res.is_err());
942             let err = res.err().unwrap();
943             prop_assert_eq!(err.code, ErrorCode::EmptyExponent);
944         }
945 
946         #[test]
947         fn f32_missing_exponent_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]?") {
948             let res = f32::from_lexical(i.as_bytes());
949             prop_assert!(res.is_err());
950             let err = res.err().unwrap();
951             prop_assert_eq!(err.code, ErrorCode::EmptyExponent);
952         }
953 
954         #[cfg(feature = "correct")]
955         #[test]
956         fn f32_roundtrip_display_proptest(i in f32::MIN..f32::MAX) {
957             let input: String = format!("{}", i);
958             prop_assert_eq!(i, f32::from_lexical(input.as_bytes()).unwrap());
959         }
960 
961         #[cfg(feature = "correct")]
962         #[test]
963         fn f32_roundtrip_debug_proptest(i in f32::MIN..f32::MAX) {
964             let input: String = format!("{:?}", i);
965             prop_assert_eq!(i, f32::from_lexical(input.as_bytes()).unwrap());
966         }
967 
968         #[cfg(feature = "correct")]
969         #[test]
970         fn f32_roundtrip_scientific_proptest(i in f32::MIN..f32::MAX) {
971             let input: String = format!("{:e}", i);
972             prop_assert_eq!(i, f32::from_lexical(input.as_bytes()).unwrap());
973         }
974 
975         #[test]
976         fn f64_invalid_proptest(i in r"[+-]?[0-9]{2}[^\deE]?\.[^\deE]?[0-9]{2}[^\deE]?e[+-]?[0-9]+[^\deE]") {
977             let res = f64::from_lexical(i.as_bytes());
978             prop_assert!(res.is_err());
979             let err = res.err().unwrap();
980             prop_assert_eq!(err.code, ErrorCode::InvalidDigit);
981         }
982 
983         #[test]
984         fn f64_double_sign_proptest(i in r"[+-]{2}[0-9]{2}\.[0-9]{2}e[+-]?[0-9]+") {
985             let res = f64::from_lexical(i.as_bytes());
986             prop_assert!(res.is_err());
987             let err = res.err().unwrap();
988             prop_assert!(err.code == ErrorCode::InvalidDigit || err.code == ErrorCode::EmptyMantissa);
989             prop_assert!(err.index == 0 || err.index == 1);
990         }
991 
992         #[test]
993         fn f64_sign_or_dot_only_proptest(i in r"[+-]?\.?") {
994             let res = f64::from_lexical(i.as_bytes());
995             prop_assert!(res.is_err());
996             let err = res.err().unwrap();
997             prop_assert!(err.code == ErrorCode::Empty || err.code == ErrorCode::EmptyMantissa);
998             prop_assert!(err.index == 0 || err.index == 1);
999         }
1000 
1001         #[test]
1002         fn f64_double_exponent_sign_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]{2}[0-9]+") {
1003             let res = f64::from_lexical(i.as_bytes());
1004             prop_assert!(res.is_err());
1005             let err = res.err().unwrap();
1006             prop_assert_eq!(err.code, ErrorCode::EmptyExponent);
1007         }
1008 
1009         #[test]
1010         fn f64_missing_exponent_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]?") {
1011             let res = f64::from_lexical(i.as_bytes());
1012             prop_assert!(res.is_err());
1013             let err = res.err().unwrap();
1014             prop_assert_eq!(err.code, ErrorCode::EmptyExponent);
1015         }
1016 
1017         #[cfg(feature = "correct")]
1018         #[test]
1019         fn f64_roundtrip_display_proptest(i in f64::MIN..f64::MAX) {
1020             let input: String = format!("{}", i);
1021             prop_assert_eq!(i, f64::from_lexical(input.as_bytes()).unwrap());
1022         }
1023 
1024         #[cfg(feature = "correct")]
1025         #[test]
1026         fn f64_roundtrip_debug_proptest(i in f64::MIN..f64::MAX) {
1027             let input: String = format!("{:?}", i);
1028             prop_assert_eq!(i, f64::from_lexical(input.as_bytes()).unwrap());
1029         }
1030 
1031         #[cfg(feature = "correct")]
1032         #[test]
1033         fn f64_roundtrip_scientific_proptest(i in f64::MIN..f64::MAX) {
1034             let input: String = format!("{:e}", i);
1035             prop_assert_eq!(i, f64::from_lexical(input.as_bytes()).unwrap());
1036         }
1037     }
1038 }
1039