1 //! Utilities to parse, extract, and interpret exponent components.
2 
3 use crate::atoi;
4 use crate::lib::slice;
5 use crate::util::*;
6 use super::traits::*;
7 
8 /// The actual float-type doesn't matter, it just needs to be used for
9 /// signed/unsigned detection during sign parsing.
10 type FloatType = f64;
11 
12 // EXPONENT CALCULATION
13 
14 // Calculate the scientific notation exponent without overflow.
15 //
16 // For example, 0.1 would be -1, and 10 would be 1 in base 10.
17 perftools_inline!{
18 #[cfg(feature = "correct")]
19 pub(super) fn scientific_exponent(exponent: i32, integer_digits: usize, fraction_start: usize)
20     -> i32
21 {
22     if integer_digits == 0 {
23         let fraction_start = fraction_start.try_i32_or_max();
24         exponent.saturating_sub(fraction_start).saturating_sub(1)
25     } else {
26         let integer_shift = (integer_digits - 1).try_i32_or_max();
27         exponent.saturating_add(integer_shift)
28     }
29 }}
30 
31 // Calculate the mantissa exponent without overflow.
32 //
33 // Remove the number of digits that contributed to the mantissa past
34 // the dot, and add the number of truncated digits from the mantissa,
35 // to calculate the scaling factor for the mantissa from a raw exponent.
36 perftools_inline!{
37 #[cfg(feature = "correct")]
38 pub(super) fn mantissa_exponent(raw_exponent: i32, fraction_digits: usize, truncated: usize)
39     -> i32
40 {
41     if fraction_digits > truncated {
42         raw_exponent.saturating_sub((fraction_digits - truncated).try_i32_or_max())
43     } else {
44         raw_exponent.saturating_add((truncated - fraction_digits).try_i32_or_max())
45     }
46 }}
47 
48 // EXPONENT EXTRACTORS
49 
50 // Extract exponent substring and parse exponent.
51 // Uses an abstract iterator to allow generic implementations
52 // iterators to work. This only works with greedy iterators, where we
53 // know exactly when we should stop upon encountering a given character.
54 //
55 // Precondition:
56 //      Iter should not implement ConsumedIterator, since it would break
57 //      the assumption in `extract_exponent_iltc`.
58 perftools_inline!{
59 #[allow(unused_unsafe)]
60 fn extract_and_parse_exponent<'a, Data, Iter>(
61     data: &mut Data,
62     iter: Iter,
63     bytes: &'a [u8],
64     radix: u32,
65     sign: Sign
66 )
67     -> &'a [u8]
68     where Data: FastDataInterface<'a>,
69           Iter: AsPtrIterator<'a, u8>
70 {
71     let (raw_exponent, ptr) = atoi::standalone_exponent(iter, radix, sign);
72     data.set_raw_exponent(raw_exponent);
73 
74     unsafe {
75         // Extract the exponent subslice.
76         let first = bytes.as_ptr();
77         data.set_exponent(Some(slice::from_raw_parts(first, distance(first, ptr))));
78 
79         // Return the remaining bytes.
80         let last = index!(bytes[bytes.len()..]).as_ptr();
81         slice::from_raw_parts(ptr, distance(ptr, last))
82     }
83 }}
84 
85 // Parse exponent.
86 // This only works with exponents that may contain digit separators,
87 // where the invalid (trailing) data has already been determined.
88 perftools_inline!{
89 #[cfg(feature = "format")]
90 fn parse_exponent<'a, Data>(
91     data: &mut Data,
92     bytes: &'a [u8],
93     leading: &'a [u8],
94     trailing: &'a [u8],
95     radix: u32,
96     digit_separator: u8,
97     sign: Sign
98 )
99     where Data: FastDataInterface<'a>
100 {
101     // Get an iterator over our digits and sign bits, and parse the exponent.
102     let iter = iterate_digits_ignore_separator(leading, digit_separator);
103 
104     // Parse the exponent and store the extracted digits.
105     let bytes_len = bytes.len() - trailing.len();
106     data.set_raw_exponent(atoi::standalone_exponent(iter, radix, sign).0);
107     data.set_exponent(Some(&index!(bytes[..bytes_len])));
108 }}
109 
110 // PARSE THEN EXTRACT
111 
112 // These algorithms are slightly more efficient, since they only
113 // require a single pass of the exponent string. These algorithms
114 // must be able to parse until they reach an invalid character,
115 // without any backsteps to find the correct subslice, that is,
116 // they must be greedy.
117 
118 // Extract exponent substring and parse exponent.
119 // Does not consume any digit separators.
120 perftools_inline!{
121 fn extract_exponent<'a, Data>(
122     data: &mut Data,
123     bytes: &'a [u8],
124     radix: u32,
125     digit_separator: u8
126 )
127     -> &'a [u8]
128     where Data: FastDataInterface<'a>
129 {
130     // Remove leading exponent character and parse exponent.
131     let bytes = &index!(bytes[1..]);
132     let (sign, digits) = parse_sign_no_separator::<FloatType>(bytes, digit_separator);
133     let iter = iterate_digits_no_separator(digits, digit_separator);
134     extract_and_parse_exponent(data, iter, bytes, radix, sign)
135 }}
136 
137 // Extract exponent substring and parse exponent.
138 // Consumes leading, internal, trailing, and consecutive digit separators.
139 perftools_inline!{
140 #[cfg(feature = "format")]
141 fn extract_exponent_iltc<'a, Data>(
142     data: &mut Data,
143     bytes: &'a [u8],
144     radix: u32,
145     digit_separator: u8
146 )
147     -> &'a [u8]
148     where Data: FastDataInterface<'a>
149 {
150     // Remove leading exponent character and parse exponent.
151     // We're not calling `consumed()`, so it's fine to have trailing underscores.
152     let bytes = &index!(bytes[1..]);
153     let (sign, digits) = parse_sign_lc_separator::<FloatType>(bytes, digit_separator);
154     let iter = iterate_digits_ignore_separator(digits, digit_separator);
155     extract_and_parse_exponent(data, iter, bytes, radix, sign)
156 }}
157 
158 // EXTRACT THEN PARSE
159 
160 // These algorithms are less efficient, since they first extract the
161 // subslice of valid data in the exponent, and then parse it,
162 // using 2 passes over the input data. However, because they first extract
163 // the data, they allow consumers that are not greedy, where there may
164 // be backsteps to determine if an input is actually valid after reaching
165 // the end or an invalid character.
166 
167 // Generate function definition to extraction exponent with digit separators.
168 macro_rules! extract_exponent_separator {
169     (
170         fn $name:ident,
171         sign => $sign:ident,
172         consume => $consume:ident
173     ) => (
174         perftools_inline!{
175         #[cfg(feature = "format")]
176         fn $name<'a, Data>(
177             data: &mut Data,
178             bytes: &'a [u8],
179             radix: u32,
180             digit_separator: u8
181         )
182             -> &'a [u8]
183             where Data: FastDataInterface<'a>
184         {
185             let bytes = &index!(bytes[1..]);
186             let (sign, digits) = $sign::<FloatType>(bytes, digit_separator);
187             let (leading, trailing) = $consume(digits, radix, digit_separator);
188             parse_exponent(data, bytes, leading, trailing, radix, digit_separator, sign);
189 
190             trailing
191         }}
192     );
193 }
194 
195 extract_exponent_separator!(
196     fn extract_exponent_i,
197     sign => parse_sign_no_separator,
198     consume => consume_digits_i
199 );
200 
201 extract_exponent_separator!(
202     fn extract_exponent_ic,
203     sign => parse_sign_no_separator,
204     consume => consume_digits_ic
205 );
206 
207 extract_exponent_separator!(
208     fn extract_exponent_l,
209     sign => parse_sign_l_separator,
210     consume => consume_digits_l
211 );
212 
213 extract_exponent_separator!(
214     fn extract_exponent_lc,
215     sign => parse_sign_lc_separator,
216     consume => consume_digits_lc
217 );
218 
219 extract_exponent_separator!(
220     fn extract_exponent_t,
221     sign => parse_sign_no_separator,
222     consume => consume_digits_t
223 );
224 
225 extract_exponent_separator!(
226     fn extract_exponent_tc,
227     sign => parse_sign_no_separator,
228     consume => consume_digits_tc
229 );
230 
231 extract_exponent_separator!(
232     fn extract_exponent_il,
233     sign => parse_sign_l_separator,
234     consume => consume_digits_il
235 );
236 
237 extract_exponent_separator!(
238     fn extract_exponent_ilc,
239     sign => parse_sign_lc_separator,
240     consume => consume_digits_ilc
241 );
242 
243 extract_exponent_separator!(
244     fn extract_exponent_it,
245     sign => parse_sign_no_separator,
246     consume => consume_digits_it
247 );
248 
249 extract_exponent_separator!(
250     fn extract_exponent_itc,
251     sign => parse_sign_no_separator,
252     consume => consume_digits_itc
253 );
254 
255 extract_exponent_separator!(
256     fn extract_exponent_lt,
257     sign => parse_sign_l_separator,
258     consume => consume_digits_lt
259 );
260 
261 extract_exponent_separator!(
262     fn extract_exponent_ltc,
263     sign => parse_sign_lc_separator,
264     consume => consume_digits_ltc
265 );
266 
267 extract_exponent_separator!(
268     fn extract_exponent_ilt,
269     sign => parse_sign_l_separator,
270     consume => consume_digits_ilt
271 );
272 
273 // API
274 
275 // Extract exponent without a digit separator.
276 perftools_inline!{
277 pub(crate) fn extract_exponent_no_separator<'a, Data>(data: &mut Data, bytes: &'a [u8], radix: u32, format: NumberFormat)
278     -> &'a [u8]
279     where Data: FastDataInterface<'a>
280 {
281     extract_exponent(data, bytes, radix, format.digit_separator())
282 }}
283 
284 // Extract exponent while ignoring the digit separator.
285 perftools_inline!{
286 #[cfg(feature = "format")]
287 pub(crate) fn extract_exponent_ignore_separator<'a, Data>(data: &mut Data, bytes: &'a [u8], radix: u32, format: NumberFormat)
288     -> &'a [u8]
289     where Data: FastDataInterface<'a>
290 {
291     extract_exponent_iltc(data, bytes, radix, format.digit_separator())
292 }}
293 
294 // Extract exponent with a digit separator in the exponent component.
295 perftools_inline!{
296 #[cfg(feature = "format")]
297 pub(super) fn extract_exponent_separator<'a, Data>(data: &mut Data, bytes: &'a [u8], radix: u32, format: NumberFormat)
298     -> &'a [u8]
299     where Data: FastDataInterface<'a>
300 {
301     const I: NumberFormat = NumberFormat::EXPONENT_INTERNAL_DIGIT_SEPARATOR;
302     const L: NumberFormat = NumberFormat::EXPONENT_LEADING_DIGIT_SEPARATOR;
303     const T: NumberFormat = NumberFormat::EXPONENT_TRAILING_DIGIT_SEPARATOR;
304     const C: NumberFormat = NumberFormat::EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR;
305     const IL: NumberFormat = NumberFormat::from_bits_truncate(I.bits() | L.bits());
306     const IT: NumberFormat = NumberFormat::from_bits_truncate(I.bits() | T.bits());
307     const LT: NumberFormat = NumberFormat::from_bits_truncate(L.bits() | T.bits());
308     const ILT: NumberFormat = NumberFormat::from_bits_truncate(IL.bits() | T.bits());
309     const IC: NumberFormat = NumberFormat::from_bits_truncate(I.bits() | C.bits());
310     const LC: NumberFormat = NumberFormat::from_bits_truncate(L.bits() | C.bits());
311     const TC: NumberFormat = NumberFormat::from_bits_truncate(T.bits() | C.bits());
312     const ILC: NumberFormat = NumberFormat::from_bits_truncate(IL.bits() | C.bits());
313     const ITC: NumberFormat = NumberFormat::from_bits_truncate(IT.bits() | C.bits());
314     const LTC: NumberFormat = NumberFormat::from_bits_truncate(LT.bits() | C.bits());
315     const ILTC: NumberFormat = NumberFormat::from_bits_truncate(ILT.bits() | C.bits());
316 
317     let digit_separator = format.digit_separator();
318     match format & NumberFormat::EXPONENT_DIGIT_SEPARATOR_FLAG_MASK {
319         I       => extract_exponent_i(data, bytes, radix, digit_separator),
320         IC      => extract_exponent_ic(data, bytes, radix, digit_separator),
321         L       => extract_exponent_l(data, bytes, radix, digit_separator),
322         LC      => extract_exponent_lc(data, bytes, radix, digit_separator),
323         T       => extract_exponent_t(data, bytes, radix, digit_separator),
324         TC      => extract_exponent_tc(data, bytes, radix, digit_separator),
325         IL      => extract_exponent_il(data, bytes, radix, digit_separator),
326         ILC     => extract_exponent_ilc(data, bytes, radix, digit_separator),
327         IT      => extract_exponent_it(data, bytes, radix, digit_separator),
328         ITC     => extract_exponent_itc(data, bytes, radix, digit_separator),
329         LT      => extract_exponent_lt(data, bytes, radix, digit_separator),
330         LTC     => extract_exponent_ltc(data, bytes, radix, digit_separator),
331         ILT     => extract_exponent_ilt(data, bytes, radix, digit_separator),
332         ILTC    => extract_exponent_iltc(data, bytes, radix, digit_separator),
333         _       => unreachable!()
334     }
335 }}
336 
337 // TESTS
338 // -----
339 
340 #[cfg(test)]
341 mod test {
342     use super::*;
343     use super::super::standard::*;
344 
345     #[cfg(feature = "format")]
346     use super::super::ignore::*;
347 
348     #[cfg(feature = "correct")]
349     #[test]
scientific_exponent_test()350     fn scientific_exponent_test() {
351         // 0 digits in the integer
352         assert_eq!(scientific_exponent(0, 0, 5), -6);
353         assert_eq!(scientific_exponent(10, 0, 5), 4);
354         assert_eq!(scientific_exponent(-10, 0, 5), -16);
355 
356         // >0 digits in the integer
357         assert_eq!(scientific_exponent(0, 1, 5), 0);
358         assert_eq!(scientific_exponent(0, 2, 5), 1);
359         assert_eq!(scientific_exponent(0, 2, 20), 1);
360         assert_eq!(scientific_exponent(10, 2, 20), 11);
361         assert_eq!(scientific_exponent(-10, 2, 20), -9);
362 
363         // Underflow
364         assert_eq!(scientific_exponent(i32::min_value(), 0, 0), i32::min_value());
365         assert_eq!(scientific_exponent(i32::min_value(), 0, 5), i32::min_value());
366 
367         // Overflow
368         assert_eq!(scientific_exponent(i32::max_value(), 0, 0), i32::max_value()-1);
369         assert_eq!(scientific_exponent(i32::max_value(), 5, 0), i32::max_value());
370     }
371 
372     #[cfg(feature = "correct")]
373     #[test]
mantissa_exponent_test()374     fn mantissa_exponent_test() {
375         assert_eq!(mantissa_exponent(10, 5, 0), 5);
376         assert_eq!(mantissa_exponent(0, 5, 0), -5);
377         assert_eq!(mantissa_exponent(i32::max_value(), 5, 0), i32::max_value()-5);
378         assert_eq!(mantissa_exponent(i32::max_value(), 0, 5), i32::max_value());
379         assert_eq!(mantissa_exponent(i32::min_value(), 5, 0), i32::min_value());
380         assert_eq!(mantissa_exponent(i32::min_value(), 0, 5), i32::min_value()+5);
381     }
382 
383     #[test]
extract_exponent_test()384     fn extract_exponent_test() {
385         // Allows present exponents.
386         type Data<'a> = StandardFastDataInterface<'a>;
387         let mut data = Data::new(NumberFormat::standard().unwrap());
388         extract_exponent(&mut data, b"e+23", 10, b'_');
389         assert_eq!(data.exponent(), Some(b!("+23")));
390         assert_eq!(data.raw_exponent(), 23);
391 
392         // Allows absent exponents.
393         let mut data = Data::new(NumberFormat::standard().unwrap());
394         extract_exponent(&mut data, b"e", 10, b'_');
395         assert_eq!(data.exponent(), Some(b!("")));
396         assert_eq!(data.raw_exponent(), 0);
397     }
398 
399     #[test]
400     #[cfg(feature = "format")]
extract_exponent_iltc_test()401     fn extract_exponent_iltc_test() {
402         // Allows present exponents.
403         type Data<'a> = IgnoreFastDataInterface<'a>;
404         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
405         extract_exponent_iltc(&mut data, b"e__+__2__3____", 10, b'_');
406         assert_eq!(data.exponent(), Some(b!("__+__2__3____")));
407         assert_eq!(data.raw_exponent(), 23);
408 
409         // Allows present exponents.
410         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
411         extract_exponent_iltc(&mut data, b"e__+_2_3_", 10, b'_');
412         assert_eq!(data.exponent(), Some(b!("__+_2_3_")));
413         assert_eq!(data.raw_exponent(), 23);
414 
415         // Allows present exponents.
416         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
417         extract_exponent_iltc(&mut data, b"e_+__2_3_", 10, b'_');
418         assert_eq!(data.exponent(), Some(b!("_+__2_3_")));
419         assert_eq!(data.raw_exponent(), 23);
420 
421         // Allows absent exponents.
422         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
423         extract_exponent_iltc(&mut data, b"e", 10, b'_');
424         assert_eq!(data.exponent(), Some(b!("")));
425         assert_eq!(data.raw_exponent(), 0);
426     }
427 
428     #[test]
429     #[cfg(feature = "format")]
extract_exponent_i_test()430     fn extract_exponent_i_test() {
431         // Allows present exponents.
432         type Data<'a> = IgnoreFastDataInterface<'a>;
433         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
434         extract_exponent_i(&mut data, b"e+2_3", 10, b'_');
435         assert_eq!(data.exponent(), Some(b!("+2_3")));
436         assert_eq!(data.raw_exponent(), 23);
437 
438         // Allows absent exponents.
439         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
440         extract_exponent_i(&mut data, b"e", 10, b'_');
441         assert_eq!(data.exponent(), Some(b!("")));
442         assert_eq!(data.raw_exponent(), 0);
443 
444         // Ignores invalid data.
445         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
446         extract_exponent_i(&mut data, b"e+_2_3", 10, b'_');
447         assert_eq!(data.exponent(), Some(b!("+")));
448         assert_eq!(data.raw_exponent(), 0);
449 
450         // Ignores invalid data.
451         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
452         extract_exponent_i(&mut data, b"e+2__3", 10, b'_');
453         assert_eq!(data.exponent(), Some(b!("+2")));
454         assert_eq!(data.raw_exponent(), 2);
455     }
456 
457     #[test]
458     #[cfg(feature = "format")]
extract_exponent_ic_test()459     fn extract_exponent_ic_test() {
460         // Allows present exponents.
461         type Data<'a> = IgnoreFastDataInterface<'a>;
462         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
463         extract_exponent_ic(&mut data, b"e+2__3", 10, b'_');
464         assert_eq!(data.exponent(), Some(b!("+2__3")));
465         assert_eq!(data.raw_exponent(), 23);
466 
467         // Allows absent exponents.
468         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
469         extract_exponent_ic(&mut data, b"e", 10, b'_');
470         assert_eq!(data.exponent(), Some(b!("")));
471         assert_eq!(data.raw_exponent(), 0);
472 
473         // Ignores invalid data.
474         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
475         extract_exponent_ic(&mut data, b"e+_2_3", 10, b'_');
476         assert_eq!(data.exponent(), Some(b!("+")));
477         assert_eq!(data.raw_exponent(), 0);
478 
479         // Ignores invalid data.
480         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
481         extract_exponent_ic(&mut data, b"e_+2__3", 10, b'_');
482         assert_eq!(data.exponent(), Some(b!("")));
483         assert_eq!(data.raw_exponent(), 0);
484     }
485 
486     #[test]
487     #[cfg(feature = "format")]
extract_exponent_l_test()488     fn extract_exponent_l_test() {
489         // Allows present exponents.
490         type Data<'a> = IgnoreFastDataInterface<'a>;
491         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
492         extract_exponent_l(&mut data, b"e+_23", 10, b'_');
493         assert_eq!(data.exponent(), Some(b!("+_23")));
494         assert_eq!(data.raw_exponent(), 23);
495 
496         // Allows absent exponents.
497         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
498         extract_exponent_l(&mut data, b"e", 10, b'_');
499         assert_eq!(data.exponent(), Some(b!("")));
500         assert_eq!(data.raw_exponent(), 0);
501 
502         // Ignores invalid data.
503         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
504         extract_exponent_l(&mut data, b"e+_2_3", 10, b'_');
505         assert_eq!(data.exponent(), Some(b!("+_2")));
506         assert_eq!(data.raw_exponent(), 2);
507 
508         // Ignores invalid data.
509         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
510         extract_exponent_l(&mut data, b"e_+__2__3", 10, b'_');
511         assert_eq!(data.exponent(), Some(b!("_+")));
512         assert_eq!(data.raw_exponent(), 0);
513     }
514 
515     #[test]
516     #[cfg(feature = "format")]
extract_exponent_lc_test()517     fn extract_exponent_lc_test() {
518         // Allows present exponents.
519         type Data<'a> = IgnoreFastDataInterface<'a>;
520         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
521         extract_exponent_lc(&mut data, b"e+__23", 10, b'_');
522         assert_eq!(data.exponent(), Some(b!("+__23")));
523         assert_eq!(data.raw_exponent(), 23);
524 
525         // Allows absent exponents.
526         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
527         extract_exponent_lc(&mut data, b"e", 10, b'_');
528         assert_eq!(data.exponent(), Some(b!("")));
529         assert_eq!(data.raw_exponent(), 0);
530 
531         // Ignores invalid data.
532         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
533         extract_exponent_lc(&mut data, b"e+_2_3", 10, b'_');
534         assert_eq!(data.exponent(), Some(b!("+_2")));
535         assert_eq!(data.raw_exponent(), 2);
536 
537         // Ignores invalid data.
538         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
539         extract_exponent_lc(&mut data, b"e_+__2__3", 10, b'_');
540         assert_eq!(data.exponent(), Some(b!("_+__2")));
541         assert_eq!(data.raw_exponent(), 2);
542     }
543 
544     #[test]
545     #[cfg(feature = "format")]
extract_exponent_t_test()546     fn extract_exponent_t_test() {
547         // Allows present exponents.
548         type Data<'a> = IgnoreFastDataInterface<'a>;
549         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
550         extract_exponent_t(&mut data, b"e+23_", 10, b'_');
551         assert_eq!(data.exponent(), Some(b!("+23_")));
552         assert_eq!(data.raw_exponent(), 23);
553 
554         // Allows absent exponents.
555         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
556         extract_exponent_t(&mut data, b"e", 10, b'_');
557         assert_eq!(data.exponent(), Some(b!("")));
558         assert_eq!(data.raw_exponent(), 0);
559 
560         // Ignores invalid data.
561         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
562         extract_exponent_t(&mut data, b"e+23__", 10, b'_');
563         assert_eq!(data.exponent(), Some(b!("+23")));
564         assert_eq!(data.raw_exponent(), 23);
565 
566         // Ignores invalid data.
567         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
568         extract_exponent_t(&mut data, b"e_+__2__3", 10, b'_');
569         assert_eq!(data.exponent(), Some(b!("_")));
570         assert_eq!(data.raw_exponent(), 0);
571     }
572 
573     #[test]
574     #[cfg(feature = "format")]
extract_exponent_tc_test()575     fn extract_exponent_tc_test() {
576         // Allows present exponents.
577         type Data<'a> = IgnoreFastDataInterface<'a>;
578         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
579         extract_exponent_tc(&mut data, b"e+23__", 10, b'_');
580         assert_eq!(data.exponent(), Some(b!("+23__")));
581         assert_eq!(data.raw_exponent(), 23);
582 
583         // Allows absent exponents.
584         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
585         extract_exponent_tc(&mut data, b"e", 10, b'_');
586         assert_eq!(data.exponent(), Some(b!("")));
587         assert_eq!(data.raw_exponent(), 0);
588 
589         // Ignores invalid data.
590         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
591         extract_exponent_tc(&mut data, b"e+_2_3", 10, b'_');
592         assert_eq!(data.exponent(), Some(b!("+")));
593         assert_eq!(data.raw_exponent(), 0);
594 
595         // Ignores invalid data.
596         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
597         extract_exponent_tc(&mut data, b"e_+__2__3", 10, b'_');
598         assert_eq!(data.exponent(), Some(b!("_")));
599         assert_eq!(data.raw_exponent(), 0);
600     }
601 
602     #[test]
603     #[cfg(feature = "format")]
extract_exponent_il_test()604     fn extract_exponent_il_test() {
605         // Allows present exponents.
606         type Data<'a> = IgnoreFastDataInterface<'a>;
607         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
608         extract_exponent_il(&mut data, b"e+_2_3", 10, b'_');
609         assert_eq!(data.exponent(), Some(b!("+_2_3")));
610         assert_eq!(data.raw_exponent(), 23);
611 
612         // Allows absent exponents.
613         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
614         extract_exponent_il(&mut data, b"e", 10, b'_');
615         assert_eq!(data.exponent(), Some(b!("")));
616         assert_eq!(data.raw_exponent(), 0);
617 
618         // Ignores invalid data.
619         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
620         extract_exponent_il(&mut data, b"e+23__", 10, b'_');
621         assert_eq!(data.exponent(), Some(b!("+23")));
622         assert_eq!(data.raw_exponent(), 23);
623 
624         // Ignores invalid data.
625         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
626         extract_exponent_il(&mut data, b"e+2__3__", 10, b'_');
627         assert_eq!(data.exponent(), Some(b!("+2")));
628         assert_eq!(data.raw_exponent(), 2);
629     }
630 
631     #[test]
632     #[cfg(feature = "format")]
extract_exponent_ilc_test()633     fn extract_exponent_ilc_test() {
634         // Allows present exponents.
635         type Data<'a> = IgnoreFastDataInterface<'a>;
636         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
637         extract_exponent_ilc(&mut data, b"e+__2__3", 10, b'_');
638         assert_eq!(data.exponent(), Some(b!("+__2__3")));
639         assert_eq!(data.raw_exponent(), 23);
640 
641         // Allows absent exponents.
642         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
643         extract_exponent_ilc(&mut data, b"e", 10, b'_');
644         assert_eq!(data.exponent(), Some(b!("")));
645         assert_eq!(data.raw_exponent(), 0);
646 
647         // Ignores invalid data.
648         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
649         extract_exponent_ilc(&mut data, b"e+23__", 10, b'_');
650         assert_eq!(data.exponent(), Some(b!("+23")));
651         assert_eq!(data.raw_exponent(), 23);
652 
653         // Ignores invalid data.
654         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
655         extract_exponent_ilc(&mut data, b"e+2__3__", 10, b'_');
656         assert_eq!(data.exponent(), Some(b!("+2__3")));
657         assert_eq!(data.raw_exponent(), 23);
658     }
659 
660     #[test]
661     #[cfg(feature = "format")]
extract_exponent_it_test()662     fn extract_exponent_it_test() {
663         // Allows present exponents.
664         type Data<'a> = IgnoreFastDataInterface<'a>;
665         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
666         extract_exponent_it(&mut data, b"e+2_3_", 10, b'_');
667         assert_eq!(data.exponent(), Some(b!("+2_3_")));
668         assert_eq!(data.raw_exponent(), 23);
669 
670         // Allows absent exponents.
671         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
672         extract_exponent_it(&mut data, b"e", 10, b'_');
673         assert_eq!(data.exponent(), Some(b!("")));
674         assert_eq!(data.raw_exponent(), 0);
675 
676         // Ignores invalid data.
677         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
678         extract_exponent_it(&mut data, b"e+_23", 10, b'_');
679         assert_eq!(data.exponent(), Some(b!("+")));
680         assert_eq!(data.raw_exponent(), 0);
681 
682         // Ignores invalid data.
683         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
684         extract_exponent_it(&mut data, b"e+2__3__", 10, b'_');
685         assert_eq!(data.exponent(), Some(b!("+2")));
686         assert_eq!(data.raw_exponent(), 2);
687     }
688 
689     #[test]
690     #[cfg(feature = "format")]
extract_exponent_itc_test()691     fn extract_exponent_itc_test() {
692         // Allows present exponents.
693         type Data<'a> = IgnoreFastDataInterface<'a>;
694         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
695         extract_exponent_itc(&mut data, b"e+2__3__", 10, b'_');
696         assert_eq!(data.exponent(), Some(b!("+2__3__")));
697         assert_eq!(data.raw_exponent(), 23);
698 
699         // Allows absent exponents.
700         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
701         extract_exponent_itc(&mut data, b"e", 10, b'_');
702         assert_eq!(data.exponent(), Some(b!("")));
703         assert_eq!(data.raw_exponent(), 0);
704 
705         // Ignores invalid data.
706         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
707         extract_exponent_itc(&mut data, b"e+_23", 10, b'_');
708         assert_eq!(data.exponent(), Some(b!("+")));
709         assert_eq!(data.raw_exponent(), 0);
710 
711         // Ignores invalid data.
712         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
713         extract_exponent_itc(&mut data, b"e_+2__3__", 10, b'_');
714         assert_eq!(data.exponent(), Some(b!("_")));
715         assert_eq!(data.raw_exponent(), 0);
716     }
717 
718     #[test]
719     #[cfg(feature = "format")]
extract_exponent_lt_test()720     fn extract_exponent_lt_test() {
721         // Allows present exponents.
722         type Data<'a> = IgnoreFastDataInterface<'a>;
723         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
724         extract_exponent_lt(&mut data, b"e_+_23_", 10, b'_');
725         assert_eq!(data.exponent(), Some(b!("_+_23_")));
726         assert_eq!(data.raw_exponent(), 23);
727 
728         // Allows absent exponents.
729         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
730         extract_exponent_lt(&mut data, b"e", 10, b'_');
731         assert_eq!(data.exponent(), Some(b!("")));
732         assert_eq!(data.raw_exponent(), 0);
733 
734         // Ignores invalid data.
735         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
736         extract_exponent_lt(&mut data, b"e+2_3", 10, b'_');
737         assert_eq!(data.exponent(), Some(b!("+2")));
738         assert_eq!(data.raw_exponent(), 2);
739 
740         // Ignores invalid data.
741         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
742         extract_exponent_lt(&mut data, b"e__+__2__3__", 10, b'_');
743         assert_eq!(data.exponent(), Some(b!("")));
744     }
745 
746     #[test]
747     #[cfg(feature = "format")]
extract_exponent_ltc_test()748     fn extract_exponent_ltc_test() {
749         // Allows present exponents.
750         type Data<'a> = IgnoreFastDataInterface<'a>;
751         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
752         extract_exponent_ltc(&mut data, b"e__+__23__", 10, b'_');
753         assert_eq!(data.exponent(), Some(b!("__+__23__")));
754         assert_eq!(data.raw_exponent(), 23);
755 
756         // Allows absent exponents.
757         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
758         extract_exponent_ltc(&mut data, b"e", 10, b'_');
759         assert_eq!(data.exponent(), Some(b!("")));
760         assert_eq!(data.raw_exponent(), 0);
761 
762         // Ignores invalid data.
763         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
764         extract_exponent_ltc(&mut data, b"e+2_3", 10, b'_');
765         assert_eq!(data.exponent(), Some(b!("+2")));
766         assert_eq!(data.raw_exponent(), 2);
767 
768         // Ignores invalid data.
769         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
770         extract_exponent_ltc(&mut data, b"e__+__2__3__", 10, b'_');
771         assert_eq!(data.exponent(), Some(b!("__+__2")));
772         assert_eq!(data.raw_exponent(), 2);
773     }
774 
775     #[test]
776     #[cfg(feature = "format")]
extract_exponent_ilt_test()777     fn extract_exponent_ilt_test() {
778         // Allows present exponents.
779         type Data<'a> = IgnoreFastDataInterface<'a>;
780         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
781         extract_exponent_ilt(&mut data, b"e_+_2_3_", 10, b'_');
782         assert_eq!(data.exponent(), Some(b!("_+_2_3_")));
783         assert_eq!(data.raw_exponent(), 23);
784 
785         // Allows absent exponents.
786         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
787         extract_exponent_ilt(&mut data, b"e", 10, b'_');
788         assert_eq!(data.exponent(), Some(b!("")));
789         assert_eq!(data.raw_exponent(), 0);
790 
791         // Ignores invalid data.
792         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
793         extract_exponent_ilt(&mut data, b"e__+_2_3_", 10, b'_');
794         assert_eq!(data.exponent(), Some(b!("")));
795 
796         // Ignores invalid data.
797         let mut data = Data::new(NumberFormat::ignore(b'_').unwrap());
798         extract_exponent_ilt(&mut data, b"e_+__2_3_", 10, b'_');
799         assert_eq!(data.exponent(), Some(b!("_+")));
800     }
801 }
802