facet_json/
deserialize.rs

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