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::True => Ok(Spanned {
90                    node: Outcome::Scalar(Scalar::Bool(true)),
91                    span,
92                }),
93                Token::False => Ok(Spanned {
94                    node: Outcome::Scalar(Scalar::Bool(false)),
95                    span,
96                }),
97                Token::Null => Ok(Spanned {
98                    node: Outcome::Scalar(Scalar::Null),
99                    span,
100                }),
101                Token::LBrace => Ok(Spanned {
102                    node: Outcome::ObjectStarted,
103                    span,
104                }),
105                Token::RBrace => {
106                    if expectation == Expectation::ObjectKeyOrObjectClose {
107                        Ok(Spanned {
108                            node: Outcome::ObjectEnded,
109                            span,
110                        })
111                    } else {
112                        trace!("Did not expect closing brace, expected {:?}", expectation);
113                        Err(DeserErrorKind::UnexpectedChar {
114                            got: '}',
115                            wanted: "a value",
116                        }
117                        .with_span(span))
118                    }
119                }
120                Token::LBracket => Ok(Spanned {
121                    node: Outcome::ListStarted,
122                    span,
123                }),
124                Token::RBracket => {
125                    if expectation == Expectation::ListItemOrListClose {
126                        Ok(Spanned {
127                            node: Outcome::ListEnded,
128                            span,
129                        })
130                    } else {
131                        Err(DeserErrorKind::UnexpectedChar {
132                            got: ']',
133                            wanted: "a value",
134                        }
135                        .with_span(span))
136                    }
137                }
138                Token::Colon => {
139                    if expectation == Expectation::ObjectVal {
140                        expectation = Expectation::Value;
141                        continue;
142                    } else {
143                        trace!("Did not expect ObjectValue, expected {:?}", expectation);
144                        Err(DeserErrorKind::UnexpectedChar {
145                            got: ':',
146                            wanted: "a value, not a colon",
147                        }
148                        .with_span(span))
149                    }
150                }
151                Token::Comma => match expectation {
152                    Expectation::ListItemOrListClose | Expectation::ObjectKeyOrObjectClose => {
153                        expectation = Expectation::Value;
154                        continue;
155                    }
156                    other => {
157                        trace!("Did not expect comma, expected {:?}", other);
158                        Err(DeserErrorKind::UnexpectedChar {
159                            got: ',',
160                            wanted: "<value or key>",
161                        }
162                        .with_span(span))
163                    }
164                },
165                Token::Eof => {
166                    return (
167                        nd,
168                        Err(DeserErrorKind::UnexpectedEof {
169                            wanted: "any value (got EOF)",
170                        }
171                        .with_span(span)),
172                    );
173                }
174            };
175
176            return (nd, res);
177        }
178    }
179
180    fn skip<'input, 'facet, 'shape>(
181        &mut self,
182        nd: NextData<'input, 'facet, 'shape>,
183    ) -> NextResult<
184        'input,
185        'facet,
186        'shape,
187        Span,
188        Spanned<DeserErrorKind<'shape>>,
189        Self::SpanType,
190        Self::Input<'input>,
191    >
192    where
193        'shape: 'input,
194    {
195        trace!("Starting skip at offset {}", nd.start());
196        let input = &nd.input()[nd.start()..];
197        let mut tokenizer = Tokenizer::new(input);
198
199        loop {
200            let token = match tokenizer.next_token() {
201                Ok(token) => token,
202                Err(err) => {
203                    trace!("Tokenizer error on initial token: {:?}", err.kind);
204                    return (nd, Err(convert_token_error(err)));
205                }
206            };
207
208            let res = match token.node {
209                Token::LBrace | Token::LBracket => {
210                    let mut depth = 1;
211                    let mut last_span = token.span;
212                    while depth > 0 {
213                        let token = match tokenizer.next_token() {
214                            Ok(token) => token,
215                            Err(err) => {
216                                trace!("Tokenizer error while skipping container: {:?}", err.kind);
217                                return (nd, Err(convert_token_error(err)));
218                            }
219                        };
220
221                        match token.node {
222                            Token::LBrace | Token::LBracket => {
223                                depth += 1;
224                                last_span = token.span;
225                            }
226                            Token::RBrace | Token::RBracket => {
227                                depth -= 1;
228                                last_span = token.span;
229                            }
230                            _ => {
231                                last_span = token.span;
232                            }
233                        }
234                    }
235                    (nd, Ok(last_span))
236                }
237                Token::String(_)
238                | Token::F64(_)
239                | Token::I64(_)
240                | Token::U64(_)
241                | Token::True
242                | Token::False
243                | Token::Null => (nd, Ok(token.span)),
244                Token::Colon => {
245                    // Skip colon token
246                    continue;
247                }
248                other => (
249                    nd,
250                    Err(DeserErrorKind::UnexpectedChar {
251                        got: format!("{:?}", other).chars().next().unwrap_or('?'),
252                        wanted: "value",
253                    }
254                    .with_span(Span::new(token.span.start(), token.span.len()))),
255                ),
256            };
257            let (nd, mut span) = res;
258            if let Ok(valid_span) = &mut span {
259                let offset = nd.start();
260                valid_span.start += offset;
261            }
262            return (nd, span);
263        }
264    }
265}
266
267fn convert_token_error(err: TokenError) -> Spanned<DeserErrorKind<'static>> {
268    match err.kind {
269        TokenErrorKind::UnexpectedCharacter(c) => DeserErrorKind::UnexpectedChar {
270            got: c,
271            wanted: "valid JSON character",
272        }
273        .with_span(err.span),
274        TokenErrorKind::UnexpectedEof(why) => {
275            DeserErrorKind::UnexpectedEof { wanted: why }.with_span(err.span)
276        }
277        TokenErrorKind::InvalidUtf8(s) => DeserErrorKind::InvalidUtf8(s).with_span(err.span),
278        TokenErrorKind::NumberOutOfRange(number) => {
279            DeserErrorKind::NumberOutOfRange(number).with_span(err.span)
280        }
281    }
282}