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