1mod buf;
17mod finite;
18mod infinity;
19mod nan;
20
21pub use self::{
22 buf::*,
23 finite::*,
24 infinity::*,
25 nan::*,
26};
27
28use core::{
29 fmt::{
30 self,
31 Write,
32 },
33 ops::Range,
34 str,
35};
36
37use crate::ParseError;
38
39#[derive(Debug, Clone, Eq, PartialEq)]
43pub enum ParsedDecimal<B> {
44 Finite(ParsedFinite<B>),
48 Infinity(ParsedInfinity),
52 Nan(ParsedNan<B>),
56}
57
58#[derive(Debug, Clone, Eq, PartialEq)]
65pub struct ParsedFinite<B> {
66 pub finite_buf: B,
67 pub finite_significand: ParsedSignificand,
68 pub finite_exponent: Option<ParsedExponent>,
69}
70
71#[derive(Debug, Clone, Eq, PartialEq)]
77pub struct ParsedNan<B> {
78 pub nan_buf: B,
79 pub nan_header: ParsedNanHeader,
80 pub nan_payload: Option<ParsedSignificand>,
81}
82
83#[derive(Debug, Clone, Eq, PartialEq)]
87pub struct ParsedInfinity {
88 pub is_infinity_negative: bool,
89}
90
91impl Default for ParsedInfinity {
92 fn default() -> Self {
93 ParsedInfinity {
94 is_infinity_negative: false,
95 }
96 }
97}
98
99#[derive(Debug, Clone, Eq, PartialEq)]
103pub struct ParsedSignificand {
104 pub significand_is_negative: bool,
105 pub significand_range: Range<usize>,
106 pub decimal_point: Option<ParsedDecimalPoint>,
107}
108
109impl Default for ParsedSignificand {
110 fn default() -> Self {
111 ParsedSignificand {
112 significand_is_negative: false,
113 significand_range: 0..0,
114 decimal_point: None,
115 }
116 }
117}
118
119#[derive(Debug, Clone, Eq, PartialEq)]
123pub struct ParsedDecimalPoint {
124 pub decimal_point_range: Range<usize>,
125}
126
127impl Default for ParsedDecimalPoint {
128 fn default() -> Self {
129 ParsedDecimalPoint {
130 decimal_point_range: 0..0,
131 }
132 }
133}
134
135#[derive(Debug, Clone, Eq, PartialEq)]
139pub struct ParsedExponent {
140 pub exponent_is_negative: bool,
141 pub exponent_range: Range<usize>,
142}
143
144impl Default for ParsedExponent {
145 fn default() -> Self {
146 ParsedExponent {
147 exponent_is_negative: false,
148 exponent_range: 0..0,
149 }
150 }
151}
152
153#[derive(Debug, Clone, Eq, PartialEq)]
159pub struct ParsedNanHeader {
160 pub is_nan_signaling: bool,
161 pub is_nan_negative: bool,
162}
163
164impl Default for ParsedNanHeader {
165 fn default() -> Self {
166 ParsedNanHeader {
167 is_nan_signaling: false,
168 is_nan_negative: false,
169 }
170 }
171}
172
173#[derive(Debug)]
177pub struct DecimalParser<B>(DecimalParserInner<B>);
178
179#[derive(Debug)]
180enum DecimalParserInner<B> {
181 AtStart {
182 buf: Option<B>,
183 is_negative: Option<bool>,
184 error: Option<ParseError>,
185 },
186 Finite(FiniteParser<B>),
187 Infinity(InfinityParser<B>),
188 Nan(NanParser<B>),
189}
190
191impl<'a> DecimalParser<StrTextBuf<'a>> {
192 pub fn parse_str(input: &'a str) -> Result<ParsedDecimal<StrTextBuf<'a>>, ParseError> {
193 let mut parser = DecimalParser::begin(StrTextBuf::new(input));
194
195 parser.parse_ascii(input.as_bytes())?;
196
197 parser.end()
198 }
199}
200
201impl<B: TextWriter> DecimalParser<B> {
202 pub fn begin(buf: B) -> Self {
203 DecimalParser(DecimalParserInner::AtStart {
204 buf: Some(buf),
205 error: None,
206 is_negative: None,
207 })
208 }
209
210 pub fn parse_fmt(&mut self, f: impl fmt::Display) -> Result<(), ParseError> {
211 write!(self, "{}", f).map_err(|err| self.unwrap_context(err))
212 }
213
214 pub fn parse_ascii(&mut self, mut ascii: &[u8]) -> Result<(), ParseError> {
215 while !ascii.is_empty() {
216 match self.0 {
217 DecimalParserInner::Finite(ref mut finite) => return finite.parse_ascii(ascii),
219 DecimalParserInner::AtStart {
222 ref mut is_negative,
223 ref mut buf,
224 ..
225 } => match ascii[0] {
226 b'0'..=b'9' => {
228 let mut finite = FiniteParser::begin(buf.take().expect("missing buffer"));
229
230 match is_negative {
231 Some(false) => finite.significand_is_positive(),
232 Some(true) => finite.significand_is_negative(),
233 _ => (),
234 }
235
236 finite.push_significand_digit(ascii[0]);
237
238 self.0 = DecimalParserInner::Finite(finite);
239 }
240 b'-' if is_negative.is_none() => *is_negative = Some(true),
243 b'+' if is_negative.is_none() => *is_negative = Some(false),
245 b's' | b'S' => {
247 let mut nan = NanParser::begin(buf.take().expect("missing buffer"));
248
249 match is_negative {
250 Some(false) => nan.nan_is_positive(b'+'),
251 Some(true) => nan.nan_is_negative(b'-'),
252 _ => (),
253 }
254
255 nan.nan_is_signaling(ascii[0]);
256
257 self.0 = DecimalParserInner::Nan(nan);
258 }
259 b'n' | b'N' => {
261 let mut nan = NanParser::begin(buf.take().expect("missing buffer"));
262
263 match is_negative {
264 Some(false) => nan.nan_is_positive(b'+'),
265 Some(true) => nan.nan_is_negative(b'-'),
266 _ => (),
267 }
268
269 nan.nan_is_quiet(ascii[0]);
270
271 self.0 = DecimalParserInner::Nan(nan);
272 }
273 b'i' | b'I' => {
275 let mut inf = InfinityParser::begin(buf.take().expect("missing buffer"));
276
277 match is_negative {
278 Some(false) => inf.infinity_is_positive(),
279 Some(true) => inf.infinity_is_negative(),
280 _ => (),
281 }
282
283 inf.advance(ascii[0]);
284
285 self.0 = DecimalParserInner::Infinity(inf)
286 }
287 c => {
289 return Err(ParseError::unexpected_char(
290 c,
291 "a finite number, infinity, or NaN",
292 ))
293 }
294 },
295 DecimalParserInner::Infinity(ref mut infinity) => {
297 return infinity.parse_ascii(ascii);
298 }
299 DecimalParserInner::Nan(ref mut nan) => {
301 return nan.parse_ascii(ascii);
302 }
303 }
304
305 ascii = &ascii[1..];
306 }
307
308 Ok(())
309 }
310
311 pub fn end(self) -> Result<ParsedDecimal<B>, ParseError> {
312 match self.0 {
313 DecimalParserInner::Finite(finite) => Ok(ParsedDecimal::Finite(finite.end()?)),
314 DecimalParserInner::Infinity(infinity) => Ok(ParsedDecimal::Infinity(infinity.end()?)),
315 DecimalParserInner::Nan(nan) => Ok(ParsedDecimal::Nan(nan.end()?)),
316 DecimalParserInner::AtStart { .. } => Err(ParseError::unexpected_end(
317 "a finite number, infinity, or NaN",
318 )),
319 }
320 }
321
322 pub fn context(&mut self, err: ParseError) -> fmt::Error {
323 match self.0 {
324 DecimalParserInner::AtStart { ref mut error, .. } => {
325 *error = Some(err);
326
327 fmt::Error
328 }
329 DecimalParserInner::Finite(ref mut parser) => parser.context(err),
330 DecimalParserInner::Infinity(ref mut parser) => parser.context(err),
331 DecimalParserInner::Nan(ref mut parser) => parser.context(err),
332 }
333 }
334
335 pub fn unwrap_context(&mut self, err: fmt::Error) -> ParseError {
336 match self.0 {
337 DecimalParserInner::AtStart { ref mut error, .. } => {
338 error.take().unwrap_or_else(ParseError::source)
339 }
340 DecimalParserInner::Finite(ref mut parser) => parser.unwrap_context(err),
341 DecimalParserInner::Infinity(ref mut parser) => parser.unwrap_context(err),
342 DecimalParserInner::Nan(ref mut parser) => parser.unwrap_context(err),
343 }
344 }
345}
346
347impl<B: TextWriter> Write for DecimalParser<B> {
348 fn write_str(&mut self, s: &str) -> fmt::Result {
349 self.parse_ascii(s.as_bytes())
350 .map_err(|err| self.context(err))
351 }
352}
353
354#[cfg(test)]
355mod tests {
356 use super::*;
357
358 #[test]
359 fn parse_decimal_propagates_input_to_sub_parsers() {
360 for (input, expected) in &[
361 (
362 "inf",
363 ParsedDecimal::<StrTextBuf>::Infinity(ParsedInfinity {
364 is_infinity_negative: false,
365 }),
366 ),
367 (
368 "-inf",
369 ParsedDecimal::<StrTextBuf>::Infinity(ParsedInfinity {
370 is_infinity_negative: true,
371 }),
372 ),
373 (
374 "NaN",
375 ParsedDecimal::<StrTextBuf>::Nan(ParsedNan {
376 nan_buf: StrTextBuf::at_end("NaN"),
377 nan_header: ParsedNanHeader {
378 is_nan_signaling: false,
379 is_nan_negative: false,
380 },
381 nan_payload: None,
382 }),
383 ),
384 (
385 "-NaN",
386 ParsedDecimal::<StrTextBuf>::Nan(ParsedNan {
387 nan_buf: StrTextBuf::at_end("-NaN"),
388 nan_header: ParsedNanHeader {
389 is_nan_signaling: false,
390 is_nan_negative: true,
391 },
392 nan_payload: None,
393 }),
394 ),
395 (
396 "+NaN",
397 ParsedDecimal::<StrTextBuf>::Nan(ParsedNan {
398 nan_buf: StrTextBuf::at_end("+NaN"),
399 nan_header: ParsedNanHeader {
400 is_nan_signaling: false,
401 is_nan_negative: false,
402 },
403 nan_payload: None,
404 }),
405 ),
406 (
407 "sNaN",
408 ParsedDecimal::<StrTextBuf>::Nan(ParsedNan {
409 nan_buf: StrTextBuf::at_end("sNaN"),
410 nan_header: ParsedNanHeader {
411 is_nan_signaling: true,
412 is_nan_negative: false,
413 },
414 nan_payload: None,
415 }),
416 ),
417 (
418 "-sNaN",
419 ParsedDecimal::<StrTextBuf>::Nan(ParsedNan {
420 nan_buf: StrTextBuf::at_end("-sNaN"),
421 nan_header: ParsedNanHeader {
422 is_nan_signaling: true,
423 is_nan_negative: true,
424 },
425 nan_payload: None,
426 }),
427 ),
428 (
429 "+sNaN",
430 ParsedDecimal::<StrTextBuf>::Nan(ParsedNan {
431 nan_buf: StrTextBuf::at_end("+sNaN"),
432 nan_header: ParsedNanHeader {
433 is_nan_signaling: true,
434 is_nan_negative: false,
435 },
436 nan_payload: None,
437 }),
438 ),
439 (
440 "1.23456e7",
441 ParsedDecimal::<StrTextBuf>::Finite(ParsedFinite {
442 finite_buf: StrTextBuf::at_end("1.23456e7"),
443 finite_significand: ParsedSignificand {
444 significand_range: 0..7,
445 decimal_point: Some(ParsedDecimalPoint {
446 decimal_point_range: 1..2,
447 }),
448 ..Default::default()
449 },
450 finite_exponent: Some(ParsedExponent {
451 exponent_range: 8..9,
452 ..Default::default()
453 }),
454 }),
455 ),
456 (
457 "-1.23456e7",
458 ParsedDecimal::<StrTextBuf>::Finite(ParsedFinite {
459 finite_buf: StrTextBuf::at_end("-1.23456e7"),
460 finite_significand: ParsedSignificand {
461 significand_is_negative: true,
462 significand_range: 1..8,
463 decimal_point: Some(ParsedDecimalPoint {
464 decimal_point_range: 2..3,
465 }),
466 },
467 finite_exponent: Some(ParsedExponent {
468 exponent_is_negative: false,
469 exponent_range: 9..10,
470 }),
471 }),
472 ),
473 ] {
474 let mut parser = DecimalParser::begin(StrTextBuf::new(input));
475 parser.write_str(input).expect("failed to parse");
476 let parsed = parser.end().expect("failed to parse");
477
478 assert_eq!(expected, &parsed, "{}", input);
479 }
480 }
481
482 #[test]
483 fn parse_finite_valid() {
484 for (input, expected) in &[
485 (
486 "0",
487 ParsedFinite {
488 finite_buf: StrTextBuf::at_end("0"),
489 finite_significand: ParsedSignificand {
490 significand_is_negative: false,
491 significand_range: 0..1,
492 decimal_point: None,
493 },
494 finite_exponent: None,
495 },
496 ),
497 (
498 "-0",
499 ParsedFinite {
500 finite_buf: StrTextBuf::at_end("-0"),
501 finite_significand: ParsedSignificand {
502 significand_is_negative: true,
503 significand_range: 1..2,
504 decimal_point: None,
505 },
506 finite_exponent: None,
507 },
508 ),
509 (
510 "+0",
511 ParsedFinite {
512 finite_buf: StrTextBuf::at_end("+0"),
513 finite_significand: ParsedSignificand {
514 significand_is_negative: false,
515 significand_range: 1..2,
516 decimal_point: None,
517 },
518 finite_exponent: None,
519 },
520 ),
521 (
522 "00",
523 ParsedFinite {
524 finite_buf: StrTextBuf::at_end("00"),
525 finite_significand: ParsedSignificand {
526 significand_is_negative: false,
527 significand_range: 0..2,
528 decimal_point: None,
529 },
530 finite_exponent: None,
531 },
532 ),
533 (
534 "0.0",
535 ParsedFinite {
536 finite_buf: StrTextBuf::at_end("0.0"),
537 finite_significand: ParsedSignificand {
538 significand_is_negative: false,
539 significand_range: 0..3,
540 decimal_point: Some(ParsedDecimalPoint {
541 decimal_point_range: 1..2,
542 }),
543 },
544 finite_exponent: None,
545 },
546 ),
547 (
548 "0.00",
549 ParsedFinite {
550 finite_buf: StrTextBuf::at_end("0.00"),
551 finite_significand: ParsedSignificand {
552 significand_is_negative: false,
553 significand_range: 0..4,
554 decimal_point: Some(ParsedDecimalPoint {
555 decimal_point_range: 1..2,
556 }),
557 },
558 finite_exponent: None,
559 },
560 ),
561 (
562 "123",
563 ParsedFinite {
564 finite_buf: StrTextBuf::at_end("123"),
565 finite_significand: ParsedSignificand {
566 significand_is_negative: false,
567 significand_range: 0..3,
568 decimal_point: None,
569 },
570 finite_exponent: None,
571 },
572 ),
573 (
574 "123.456",
575 ParsedFinite {
576 finite_buf: StrTextBuf::at_end("123.456"),
577 finite_significand: ParsedSignificand {
578 significand_is_negative: false,
579 significand_range: 0..7,
580 decimal_point: Some(ParsedDecimalPoint {
581 decimal_point_range: 3..4,
582 }),
583 },
584 finite_exponent: None,
585 },
586 ),
587 (
588 "123e456",
589 ParsedFinite {
590 finite_buf: StrTextBuf::at_end("123e456"),
591 finite_significand: ParsedSignificand {
592 significand_is_negative: false,
593 significand_range: 0..3,
594 decimal_point: None,
595 },
596 finite_exponent: Some(ParsedExponent {
597 exponent_is_negative: false,
598 exponent_range: 4..7,
599 }),
600 },
601 ),
602 (
603 "123.456e789",
604 ParsedFinite {
605 finite_buf: StrTextBuf::at_end("123.456e789"),
606 finite_significand: ParsedSignificand {
607 significand_is_negative: false,
608 significand_range: 0..7,
609 decimal_point: Some(ParsedDecimalPoint {
610 decimal_point_range: 3..4,
611 }),
612 },
613 finite_exponent: Some(ParsedExponent {
614 exponent_is_negative: false,
615 exponent_range: 8..11,
616 }),
617 },
618 ),
619 (
620 "123e-456",
621 ParsedFinite {
622 finite_buf: StrTextBuf::at_end("123e-456"),
623 finite_significand: ParsedSignificand {
624 significand_is_negative: false,
625 significand_range: 0..3,
626 decimal_point: None,
627 },
628 finite_exponent: Some(ParsedExponent {
629 exponent_is_negative: true,
630 exponent_range: 5..8,
631 }),
632 },
633 ),
634 (
635 "123.456e-789",
636 ParsedFinite {
637 finite_buf: StrTextBuf::at_end("123.456e-789"),
638 finite_significand: ParsedSignificand {
639 significand_is_negative: false,
640 significand_range: 0..7,
641 decimal_point: Some(ParsedDecimalPoint {
642 decimal_point_range: 3..4,
643 }),
644 },
645 finite_exponent: Some(ParsedExponent {
646 exponent_is_negative: true,
647 exponent_range: 9..12,
648 }),
649 },
650 ),
651 ] {
652 let mut parser = FiniteParser::begin(StrTextBuf::new(input));
653 parser.write_str(input).expect("failed to parse");
654 let parsed = parser.end().expect("failed to parse");
655
656 assert_eq!(expected, &parsed, "{}", input);
657 }
658 }
659
660 #[test]
661 fn parse_inf_valid() {
662 for (input, expected) in &[
663 (
664 "inf",
665 ParsedInfinity {
666 is_infinity_negative: false,
667 },
668 ),
669 (
670 "-inf",
671 ParsedInfinity {
672 is_infinity_negative: true,
673 },
674 ),
675 (
676 "+inf",
677 ParsedInfinity {
678 is_infinity_negative: false,
679 },
680 ),
681 (
682 "infinity",
683 ParsedInfinity {
684 is_infinity_negative: false,
685 },
686 ),
687 (
688 "-infinity",
689 ParsedInfinity {
690 is_infinity_negative: true,
691 },
692 ),
693 (
694 "+infinity",
695 ParsedInfinity {
696 is_infinity_negative: false,
697 },
698 ),
699 (
700 "INF",
701 ParsedInfinity {
702 is_infinity_negative: false,
703 },
704 ),
705 (
706 "-INf",
707 ParsedInfinity {
708 is_infinity_negative: true,
709 },
710 ),
711 (
712 "+INf",
713 ParsedInfinity {
714 is_infinity_negative: false,
715 },
716 ),
717 (
718 "InFinITY",
719 ParsedInfinity {
720 is_infinity_negative: false,
721 },
722 ),
723 ] {
724 let mut parser = InfinityParser::begin(StrTextBuf::new(input));
725 parser.write_str(input).expect("failed to parse");
726 let parsed = parser.end().expect("failed to parse");
727
728 assert_eq!(expected, &parsed, "{}", input);
729 }
730 }
731
732 #[test]
733 fn parse_nan_valid() {
734 for (input, expected) in &[
735 (
736 "nan",
737 ParsedNan {
738 nan_buf: StrTextBuf::at_end("nan"),
739 nan_header: ParsedNanHeader {
740 is_nan_signaling: false,
741 is_nan_negative: false,
742 },
743 nan_payload: None,
744 },
745 ),
746 (
747 "-nan",
748 ParsedNan {
749 nan_buf: StrTextBuf::at_end("-nan"),
750 nan_header: ParsedNanHeader {
751 is_nan_signaling: false,
752 is_nan_negative: true,
753 },
754 nan_payload: None,
755 },
756 ),
757 (
758 "+nan",
759 ParsedNan {
760 nan_buf: StrTextBuf::at_end("+nan"),
761 nan_header: ParsedNanHeader {
762 is_nan_signaling: false,
763 is_nan_negative: false,
764 },
765 nan_payload: None,
766 },
767 ),
768 (
769 "snan",
770 ParsedNan {
771 nan_buf: StrTextBuf::at_end("snan"),
772 nan_header: ParsedNanHeader {
773 is_nan_signaling: true,
774 is_nan_negative: false,
775 },
776 nan_payload: None,
777 },
778 ),
779 (
780 "-snan",
781 ParsedNan {
782 nan_buf: StrTextBuf::at_end("-snan"),
783 nan_header: ParsedNanHeader {
784 is_nan_signaling: true,
785 is_nan_negative: true,
786 },
787 nan_payload: None,
788 },
789 ),
790 (
791 "+snan",
792 ParsedNan {
793 nan_buf: StrTextBuf::at_end("+snan"),
794 nan_header: ParsedNanHeader {
795 is_nan_signaling: true,
796 is_nan_negative: false,
797 },
798 nan_payload: None,
799 },
800 ),
801 (
802 "NaN",
803 ParsedNan {
804 nan_buf: StrTextBuf::at_end("NaN"),
805 nan_header: ParsedNanHeader {
806 is_nan_signaling: false,
807 is_nan_negative: false,
808 },
809 nan_payload: None,
810 },
811 ),
812 (
813 "SNAN",
814 ParsedNan {
815 nan_buf: StrTextBuf::at_end("SNAN"),
816 nan_header: ParsedNanHeader {
817 is_nan_signaling: true,
818 is_nan_negative: false,
819 },
820 nan_payload: None,
821 },
822 ),
823 (
824 "nan(1234)",
825 ParsedNan {
826 nan_buf: StrTextBuf::at_end("nan(1234)"),
827 nan_header: ParsedNanHeader {
828 is_nan_signaling: false,
829 is_nan_negative: false,
830 },
831 nan_payload: Some(ParsedSignificand {
832 significand_range: 4..8,
833 ..Default::default()
834 }),
835 },
836 ),
837 (
838 "nan()",
839 ParsedNan {
840 nan_buf: StrTextBuf::at_end("nan()"),
841 nan_header: ParsedNanHeader {
842 is_nan_signaling: false,
843 is_nan_negative: false,
844 },
845 nan_payload: Some(ParsedSignificand {
846 significand_range: 4..4,
847 ..Default::default()
848 }),
849 },
850 ),
851 ] {
852 let mut parser = NanParser::begin(StrTextBuf::new(input));
853 let _ = parser.write_str(input);
854
855 let nan = parser.end().expect("failed to parse");
856
857 assert_eq!(expected, &nan, "{}", input);
858 }
859 }
860
861 #[test]
862 fn parse_fails_on_buffer_too_small() {
863 let expected_err = "the buffer is too small";
864
865 let mut buf = DecimalParser::begin(ArrayTextBuf::<1>::default());
866 let err = buf.parse_ascii(b"123").unwrap_err();
867 assert_eq!(expected_err, &err.to_string());
868
869 let mut buf = FiniteParser::begin(ArrayTextBuf::<1>::default());
870 let err = buf.parse_ascii(b"123").unwrap_err();
871 assert_eq!(expected_err, &err.to_string());
872
873 let mut buf = InfinityParser::begin(ArrayTextBuf::<1>::default());
874 let err = buf.parse_ascii(b"inf").unwrap_err();
875 assert_eq!(expected_err, &err.to_string());
876
877 let mut buf = NanParser::begin(ArrayTextBuf::<1>::default());
878 let err = buf.parse_ascii(b"nan").unwrap_err();
879 assert_eq!(expected_err, &err.to_string());
880 }
881
882 #[test]
883 fn parse_finite_invalid() {
884 let (input, expected_err) = &("", "unexpected end of input, expected a sign or digit");
885 let actual_err = FiniteParser::parse_str(input).unwrap_err();
886
887 assert_eq!(expected_err, &actual_err.to_string(), "{}", input);
888 }
889
890 #[test]
891 fn parse_invalid() {
892 for (input, expected_err) in &[
893 (
894 "",
895 "unexpected end of input, expected a finite number, infinity, or NaN",
896 ),
897 (
898 "-",
899 "unexpected end of input, expected a finite number, infinity, or NaN",
900 ),
901 (
902 "+",
903 "unexpected end of input, expected a finite number, infinity, or NaN",
904 ),
905 ("1e", "unexpected end of input, expected a sign or digit"),
906 ("1e-", "unexpected end of input, expected any digit"),
907 ("1e+", "unexpected end of input, expected any digit"),
908 ("in", "unexpected end of input, expected `f`"),
909 ("n", "unexpected end of input, expected `a`"),
910 ("s", "unexpected end of input, expected `n`"),
911 ("nan(", "unexpected end of input, expected `)`"),
912 ("nan(123", "unexpected end of input, expected `)`"),
913 ("snan(", "unexpected end of input, expected `)`"),
914 ("snan(123", "unexpected end of input, expected `)`"),
915 (
916 "x",
917 "unexpected character `x`, expected a finite number, infinity, or NaN",
918 ),
919 (
920 "-x",
921 "unexpected character `x`, expected a finite number, infinity, or NaN",
922 ),
923 (
924 "+x",
925 "unexpected character `x`, expected a finite number, infinity, or NaN",
926 ),
927 ("1x", "unexpected character `x`, expected any digit"),
928 ("1ex", "unexpected character `x`, expected any digit"),
929 ("1e-x", "unexpected character `x`, expected any digit"),
930 ("1e+x", "unexpected character `x`, expected any digit"),
931 ("1.", "unexpected end of input, expected a sign or digit"),
932 ("inx", "unexpected character `x`, expected `f`"),
933 ("infinityx", "unexpected character `x`"),
934 ("nx", "unexpected character `x`"),
935 ("snx", "unexpected character `x`"),
936 ("nan()x", "unexpected character `x`"),
937 ("snan()x", "unexpected character `x`"),
938 (
939 "--",
940 "unexpected character `-`, expected a finite number, infinity, or NaN",
941 ),
942 (
943 "++",
944 "unexpected character `+`, expected a finite number, infinity, or NaN",
945 ),
946 (
947 "-+",
948 "unexpected character `+`, expected a finite number, infinity, or NaN",
949 ),
950 (
951 "+-",
952 "unexpected character `-`, expected a finite number, infinity, or NaN",
953 ),
954 (
955 ".",
956 "unexpected character `.`, expected a finite number, infinity, or NaN",
957 ),
958 (
959 "..",
960 "unexpected character `.`, expected a finite number, infinity, or NaN",
961 ),
962 ("1.3.2", "unexpected character `.`, expected any digit"),
963 ("1e1.1", "unexpected character `.`, expected any digit"),
964 ("1-", "unexpected character `-`, expected any digit"),
965 ("1+", "unexpected character `+`, expected any digit"),
966 ("1e1-", "unexpected character `-`, expected any digit"),
967 ("1e1+", "unexpected character `+`, expected any digit"),
968 ("n(", "unexpected character `(`"),
969 ("sn(", "unexpected character `(`"),
970 ("nan(1.2)", "unexpected character `.`"),
971 ("snan(1.2)", "unexpected character `.`"),
972 ("nan(-1)", "unexpected character `-`"),
973 ("snan(-1)", "unexpected character `-`"),
974 ("nan(1e2", "unexpected character `e`"),
975 ("snan(1e2)", "unexpected character `e`"),
976 ] {
977 let actual_err = DecimalParser::parse_str(input).unwrap_err();
978
979 assert_eq!(expected_err, &actual_err.to_string(), "{}", input);
980 }
981 }
982
983 #[test]
984 fn parse_fmt_no_content() {
985 struct Empty;
986
987 impl fmt::Display for Empty {
988 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
989 Ok(())
990 }
991 }
992
993 let mut parser = DecimalParser::begin(ArrayTextBuf::<32>::default());
994 parser.parse_fmt(Empty).unwrap();
995
996 let expected_err = "unexpected end of input, expected a finite number, infinity, or NaN";
997
998 assert_eq!(expected_err, &parser.end().unwrap_err().to_string());
999 }
1000
1001 #[test]
1002 fn parse_fmt_failing() {
1003 struct Failing;
1004
1005 impl fmt::Display for Failing {
1006 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
1007 Err(fmt::Error)
1008 }
1009 }
1010
1011 let mut parser = DecimalParser::begin(ArrayTextBuf::<32>::default());
1012
1013 let expected_err = "the source produced an error while parsing";
1014
1015 assert_eq!(
1016 expected_err,
1017 &parser.parse_fmt(Failing).unwrap_err().to_string()
1018 );
1019 }
1020}