facet_json/
deserialize.rs

1use alloc::format;
2
3use facet_core::Facet;
4use facet_deserialize::{
5    Cooked, Expectation, Format, NextData, NextResult, Outcome, Scalar, Span, Spannable, Spanned,
6};
7pub use facet_deserialize::{DeserError, DeserErrorKind};
8use log::trace;
9
10use crate::tokenizer::{Token, TokenError, TokenErrorKind, Tokenizer};
11
12/// Deserialize JSON from a given byte slice
13pub fn from_slice<'input, 'facet, 'shape, T: Facet<'facet>>(
14    input: &'input [u8],
15) -> Result<T, DeserError<'input, 'shape>>
16where
17    'input: 'facet,
18{
19    facet_deserialize::deserialize(input, crate::Json)
20}
21
22/// Deserialize JSON from a UTF-8 string slice
23pub fn from_str<'input, 'facet, 'shape, T: Facet<'facet>>(
24    input: &'input str,
25) -> Result<T, DeserError<'input, 'shape>>
26where
27    'input: 'facet,
28{
29    from_slice(input.as_bytes())
30}
31
32impl Format for crate::Json {
33    type Input<'input> = [u8];
34    type SpanType = Cooked;
35
36    fn source(&self) -> &'static str {
37        "json"
38    }
39
40    fn next<'input, 'facet, 'shape>(
41        &mut self,
42        nd: NextData<'input, 'facet, 'shape>,
43        mut expectation: Expectation,
44    ) -> NextResult<
45        'input,
46        'facet,
47        'shape,
48        Spanned<Outcome<'input>, Self::SpanType>,
49        Spanned<DeserErrorKind<'shape>, Self::SpanType>,
50        Self::SpanType,
51        Self::Input<'input>,
52    >
53    where
54        'shape: 'input,
55    {
56        let input = &nd.input()[nd.start()..];
57        let mut tokenizer = Tokenizer::new(input);
58
59        loop {
60            let token = match tokenizer.next_token() {
61                Ok(token) => token,
62                Err(err) => {
63                    trace!("Tokenizer error in next: {:?}", err.kind);
64                    return (nd, Err(convert_token_error(err)));
65                }
66            };
67
68            // Adjust token span to be relative to the beginning of the overall input
69            let token_offset = nd.start();
70            let span = Span::new(token.span.start() + token_offset, token.span.len());
71
72            let res = match token.node {
73                Token::String(s) => Ok(Spanned {
74                    node: Outcome::Scalar(Scalar::String(s)),
75                    span,
76                }),
77                Token::F64(n) => Ok(Spanned {
78                    node: Outcome::Scalar(Scalar::F64(n)),
79                    span,
80                }),
81                Token::I64(n) => Ok(Spanned {
82                    node: Outcome::Scalar(Scalar::I64(n)),
83                    span,
84                }),
85                Token::U64(n) => Ok(Spanned {
86                    node: Outcome::Scalar(Scalar::U64(n)),
87                    span,
88                }),
89                Token::U128(n) => Ok(Spanned {
90                    node: Outcome::Scalar(Scalar::U128(n)),
91                    span,
92                }),
93                Token::I128(n) => Ok(Spanned {
94                    node: Outcome::Scalar(Scalar::I128(n)),
95                    span,
96                }),
97                Token::True => Ok(Spanned {
98                    node: Outcome::Scalar(Scalar::Bool(true)),
99                    span,
100                }),
101                Token::False => Ok(Spanned {
102                    node: Outcome::Scalar(Scalar::Bool(false)),
103                    span,
104                }),
105                Token::Null => Ok(Spanned {
106                    node: Outcome::Scalar(Scalar::Null),
107                    span,
108                }),
109                Token::LBrace => Ok(Spanned {
110                    node: Outcome::ObjectStarted,
111                    span,
112                }),
113                Token::RBrace => {
114                    if expectation == Expectation::ObjectKeyOrObjectClose {
115                        Ok(Spanned {
116                            node: Outcome::ObjectEnded,
117                            span,
118                        })
119                    } else {
120                        trace!("Did not expect closing brace, expected {:?}", expectation);
121                        Err(DeserErrorKind::UnexpectedChar {
122                            got: '}',
123                            wanted: "a value",
124                        }
125                        .with_span(span))
126                    }
127                }
128                Token::LBracket => Ok(Spanned {
129                    node: Outcome::ListStarted,
130                    span,
131                }),
132                Token::RBracket => {
133                    if expectation == Expectation::ListItemOrListClose {
134                        Ok(Spanned {
135                            node: Outcome::ListEnded,
136                            span,
137                        })
138                    } else {
139                        Err(DeserErrorKind::UnexpectedChar {
140                            got: ']',
141                            wanted: "a value",
142                        }
143                        .with_span(span))
144                    }
145                }
146                Token::Colon => {
147                    if expectation == Expectation::ObjectVal {
148                        expectation = Expectation::Value;
149                        continue;
150                    } else {
151                        trace!("Did not expect ObjectValue, expected {:?}", expectation);
152                        Err(DeserErrorKind::UnexpectedChar {
153                            got: ':',
154                            wanted: "a value, not a colon",
155                        }
156                        .with_span(span))
157                    }
158                }
159                Token::Comma => match expectation {
160                    Expectation::ListItemOrListClose | Expectation::ObjectKeyOrObjectClose => {
161                        expectation = Expectation::Value;
162                        continue;
163                    }
164                    other => {
165                        trace!("Did not expect comma, expected {:?}", other);
166                        Err(DeserErrorKind::UnexpectedChar {
167                            got: ',',
168                            wanted: "<value or key>",
169                        }
170                        .with_span(span))
171                    }
172                },
173                Token::Eof => {
174                    return (
175                        nd,
176                        Err(DeserErrorKind::UnexpectedEof {
177                            wanted: "any value (got EOF)",
178                        }
179                        .with_span(span)),
180                    );
181                }
182            };
183
184            return (nd, res);
185        }
186    }
187
188    fn skip<'input, 'facet, 'shape>(
189        &mut self,
190        nd: NextData<'input, 'facet, 'shape>,
191    ) -> NextResult<
192        'input,
193        'facet,
194        'shape,
195        Span,
196        Spanned<DeserErrorKind<'shape>>,
197        Self::SpanType,
198        Self::Input<'input>,
199    >
200    where
201        'shape: 'input,
202    {
203        trace!("Starting skip at offset {}", nd.start());
204        let input = &nd.input()[nd.start()..];
205        let mut tokenizer = Tokenizer::new(input);
206
207        loop {
208            let token = match tokenizer.next_token() {
209                Ok(token) => token,
210                Err(err) => {
211                    trace!("Tokenizer error on initial token: {:?}", err.kind);
212                    return (nd, Err(convert_token_error(err)));
213                }
214            };
215
216            let res = match token.node {
217                Token::LBrace | Token::LBracket => {
218                    let mut depth = 1;
219                    let mut last_span = token.span;
220                    while depth > 0 {
221                        let token = match tokenizer.next_token() {
222                            Ok(token) => token,
223                            Err(err) => {
224                                trace!("Tokenizer error while skipping container: {:?}", err.kind);
225                                return (nd, Err(convert_token_error(err)));
226                            }
227                        };
228
229                        match token.node {
230                            Token::LBrace | Token::LBracket => {
231                                depth += 1;
232                                last_span = token.span;
233                            }
234                            Token::RBrace | Token::RBracket => {
235                                depth -= 1;
236                                last_span = token.span;
237                            }
238                            _ => {
239                                last_span = token.span;
240                            }
241                        }
242                    }
243                    (nd, Ok(last_span))
244                }
245                Token::String(_)
246                | Token::F64(_)
247                | Token::I64(_)
248                | Token::U64(_)
249                | Token::True
250                | Token::False
251                | Token::Null => (nd, Ok(token.span)),
252                Token::Colon => {
253                    // Skip colon token
254                    continue;
255                }
256                other => (
257                    nd,
258                    Err(DeserErrorKind::UnexpectedChar {
259                        got: format!("{:?}", other).chars().next().unwrap_or('?'),
260                        wanted: "value",
261                    }
262                    .with_span(Span::new(token.span.start(), token.span.len()))),
263                ),
264            };
265            let (nd, mut span) = res;
266            if let Ok(valid_span) = &mut span {
267                let offset = nd.start();
268                valid_span.start += offset;
269            }
270            return (nd, span);
271        }
272    }
273}
274
275fn convert_token_error(err: TokenError) -> Spanned<DeserErrorKind<'static>> {
276    match err.kind {
277        TokenErrorKind::UnexpectedCharacter(c) => DeserErrorKind::UnexpectedChar {
278            got: c,
279            wanted: "valid JSON character",
280        }
281        .with_span(err.span),
282        TokenErrorKind::UnexpectedEof(why) => {
283            DeserErrorKind::UnexpectedEof { wanted: why }.with_span(err.span)
284        }
285        TokenErrorKind::InvalidUtf8(s) => DeserErrorKind::InvalidUtf8(s).with_span(err.span),
286        TokenErrorKind::NumberOutOfRange(number) => {
287            DeserErrorKind::NumberOutOfRange(number).with_span(err.span)
288        }
289    }
290}