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