json_syntax/parse/
number.rs1use super::{Context, Error, Parse, Parser};
2use crate::{NumberBuf, SMALL_STRING_CAPACITY};
3use decoded_char::DecodedChar;
4use locspan::Meta;
5use smallvec::SmallVec;
6
7impl Parse for NumberBuf {
8 fn parse_in<C, E>(
9 parser: &mut Parser<C, E>,
10 context: Context,
11 ) -> Result<Meta<Self, usize>, Error<E>>
12 where
13 C: Iterator<Item = Result<DecodedChar, E>>,
14 {
15 let i = parser.begin_fragment();
16 let mut buffer: SmallVec<[u8; SMALL_STRING_CAPACITY]> = SmallVec::new();
17
18 enum State {
19 Init,
20 FirstDigit,
21 Zero,
22 NonZero,
23 FractionalFirst,
24 FractionalRest,
25 ExponentSign,
26 ExponentFirst,
27 ExponentRest,
28 }
29
30 let mut state = State::Init;
31
32 while let Some(c) = parser.peek_char()? {
33 match state {
34 State::Init => match c {
35 '-' => state = State::FirstDigit,
36 '0' => state = State::Zero,
37 '1'..='9' => state = State::NonZero,
38 _ => return Err(Error::unexpected(parser.position, Some(c))),
39 },
40 State::FirstDigit => match c {
41 '0' => state = State::Zero,
42 '1'..='9' => state = State::NonZero,
43 _ => return Err(Error::unexpected(parser.position, Some(c))),
44 },
45 State::Zero => match c {
46 '.' => state = State::FractionalFirst,
47 'e' | 'E' => state = State::ExponentSign,
48 _ => {
49 if context.follows(c) {
50 break;
51 } else {
52 return Err(Error::unexpected(parser.position, Some(c)));
53 }
54 }
55 },
56 State::NonZero => match c {
57 '0'..='9' => state = State::NonZero,
58 '.' => state = State::FractionalFirst,
59 'e' | 'E' => state = State::ExponentSign,
60 _ => {
61 if context.follows(c) {
62 break;
63 } else {
64 return Err(Error::unexpected(parser.position, Some(c)));
65 }
66 }
67 },
68 State::FractionalFirst => match c {
69 '0'..='9' => state = State::FractionalRest,
70 _ => return Err(Error::unexpected(parser.position, Some(c))),
71 },
72 State::FractionalRest => match c {
73 '0'..='9' => state = State::FractionalRest,
74 'e' | 'E' => state = State::ExponentSign,
75 _ => {
76 if context.follows(c) {
77 break;
78 } else {
79 return Err(Error::unexpected(parser.position, Some(c)));
80 }
81 }
82 },
83 State::ExponentSign => match c {
84 '+' | '-' => state = State::ExponentFirst,
85 '0'..='9' => state = State::ExponentRest,
86 _ => return Err(Error::unexpected(parser.position, Some(c))),
87 },
88 State::ExponentFirst => match c {
89 '0'..='9' => state = State::ExponentRest,
90 _ => return Err(Error::unexpected(parser.position, Some(c))),
91 },
92 State::ExponentRest => match c {
93 '0'..='9' => state = State::ExponentRest,
94 _ => {
95 if context.follows(c) {
96 break;
97 } else {
98 return Err(Error::unexpected(parser.position, Some(c)));
99 }
100 }
101 },
102 }
103
104 buffer.push(c as u8);
106 parser.next_char()?;
107 }
108
109 if matches!(
110 state,
111 State::Zero | State::NonZero | State::FractionalRest | State::ExponentRest
112 ) {
113 parser.end_fragment(i);
114 Ok(Meta(unsafe { NumberBuf::new_unchecked(buffer) }, i))
115 } else {
116 Err(Error::unexpected(parser.position, None))
117 }
118 }
119}