core_json/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![deny(missing_docs)]
4#![cfg_attr(not(test), no_std)]
5
6#[cfg(feature = "alloc")]
7extern crate alloc;
8
9mod io;
10mod stack;
11mod string;
12mod number;
13mod deserializer;
14
15pub use io::Read;
16use io::PeekableRead;
17pub use stack::*;
18use string::*;
19pub use number::{NumberSink, Number};
20pub use deserializer::{Deserializer, Value};
21use deserializer::*;
22
23/// An error incurred when deserializing.
24#[derive(Debug)]
25pub enum JsonError<'read, R: Read<'read>, S: Stack> {
26  /// An unexpected state was reached during deserialization.
27  InternalError,
28  /// An error from the reader.
29  ReadError(R::Error),
30  /// An error from the stack.
31  StackError(S::Error),
32  /// The deserializer was reused.
33  ReusedDeserializer,
34  /// The JSON had an invalid key.
35  InvalidKey,
36  /// The JSON had an invalid delimiter between the key and value (`:` expected).
37  InvalidKeyValueDelimiter,
38  /// The JSON had an invalid value.
39  InvalidValue,
40  /// The string represented by the JSON serialization was valid yet not UTF-8.
41  NotUtf8,
42  /// The JSON had a trailing comma.
43  TrailingComma,
44  /// The JSON had mismatched delimiters between the open and close of the structure.
45  MismatchedDelimiter,
46  /// Operation could not be performed given the value's type.
47  TypeError,
48}
49impl<'read, R: Read<'read>, S: Stack> Clone for JsonError<'read, R, S> {
50  #[inline(always)]
51  fn clone(&self) -> Self {
52    *self
53  }
54}
55impl<'read, R: Read<'read>, S: Stack> Copy for JsonError<'read, R, S> {}
56
57/// The type of the value.
58///
59/// https://datatracker.ietf.org/doc/html/rfc8259#section-3 defines all possible values.
60pub enum Type {
61  /// An object.
62  Object,
63  /// An array.
64  Array,
65  /// A string.
66  String,
67  /// A RFC-8259 number.
68  Number,
69  /// A boolean.
70  Bool,
71  /// The `null` unit value.
72  Null,
73}
74
75/// Get the type of the current item.
76///
77/// This does not assert it's a valid instance of this class of items. It solely asserts if this
78/// is a valid item, it will be of this type.
79#[inline(always)]
80fn kind<'read, R: Read<'read>>(reader: &PeekableRead<'read, R>) -> Type {
81  match reader.peek() {
82    b'{' => Type::Object,
83    b'[' => Type::Array,
84    b'"' => Type::String,
85    b't' | b'f' => Type::Bool,
86    b'n' => Type::Null,
87    _ => Type::Number,
88  }
89}
90
91/// A field within an object.
92pub struct Field<'read, 'parent, R: Read<'read>, S: Stack> {
93  key: StringKey<'read, 'parent, R, S>,
94}
95
96/// Handle a field.
97///
98/// This MUST be called every time a `SingleStepObjectResult::Field` is yielded, unless the
99/// deserializer is immediately terminated (such as by setting its error to `Some(_)`). This
100/// ideally would be yielded within `SingleStepObjectResult::Field`, yet that would cause every
101/// `SingleStepObjectResult` to consume the parent's borrow for the rest of its lifetime, when we
102/// only want to consume it upon `SingleStepObjectResult::Field`.
103#[inline(always)]
104fn handle_field<'read, 'parent, R: Read<'read>, S: Stack>(
105  deserializer: &'parent mut Deserializer<'read, R, S>,
106) -> Field<'read, 'parent, R, S> {
107  Field { key: StringKey(Some(String::read(deserializer))) }
108}
109
110/// Handle a string value.
111///
112/// This MUST be called every time a `SingleStepUnknownResult::String` is yielded, unless the
113/// deserializer is immediately terminated (such as by setting its error to `Some(_)`). This
114/// ideally would be yielded within `SingleStepUnknownResult::String`, yet that would cause every
115/// `SingleStepUnknownResult` to consume the parent's borrow for the rest of its lifetime, when we
116/// only want to consume it upon `SingleStepUnknownResult::String`.
117#[inline(always)]
118fn handle_string_value<'read, 'parent, R: Read<'read>, S: Stack>(
119  deserializer: &'parent mut Deserializer<'read, R, S>,
120) -> StringValue<'read, 'parent, R, S> {
121  StringValue(String::read(deserializer))
122}
123
124impl<'read, 'parent, R: Read<'read>, S: Stack> Field<'read, 'parent, R, S> {
125  /// Access the iterator for the string used as the field's key.
126  ///
127  /// The iterator will yield the individual characters within the string represented by the JSON
128  /// serialization, with all escape sequences handled.
129  ///
130  /// If the JSON underlying is invalid, the iterator will error, and while `Field::value` may
131  /// still be called, all further attempted accesses will yield an error.
132  ///
133  /// If the JSON underlying is valid yet does not represent a valid UTF-8 sequence, the iterator
134  /// will error, yet `Field::value` may still be called and deserialization may continue. The rest
135  /// of the key will not be accessible however.
136  #[inline(always)]
137  pub fn key(
138    &mut self,
139  ) -> &mut (impl use<'read, 'parent, R, S> + Iterator<Item = Result<char, JsonError<'read, R, S>>>)
140  {
141    &mut self.key
142  }
143  /// Access the field's value.
144  #[inline(always)]
145  pub fn value(mut self) -> Value<'read, 'parent, R, S> {
146    Value { deserializer: self.key.drop() }
147  }
148}
149
150impl<'read, 'parent, R: Read<'read>, S: Stack> Drop for Field<'read, 'parent, R, S> {
151  #[inline(always)]
152  fn drop(&mut self) {
153    drop(Value { deserializer: self.key.drop() });
154  }
155}
156
157/// An iterator over fields.
158pub struct FieldIterator<'read, 'parent, R: Read<'read>, S: Stack> {
159  deserializer: &'parent mut Deserializer<'read, R, S>,
160  done: bool,
161}
162
163// When this object is dropped, advance the decoder past the unread items
164impl<'read, 'parent, R: Read<'read>, S: Stack> Drop for FieldIterator<'read, 'parent, R, S> {
165  #[inline(always)]
166  fn drop(&mut self) {
167    if self.deserializer.error.is_some() {
168      return;
169    }
170
171    loop {
172      let Some(next) = self.next() else { break };
173      let next = next.map(|_| ());
174      match next {
175        Ok(()) => {}
176        Err(e) => {
177          self.deserializer.error = Some(e);
178          break;
179        }
180      }
181    }
182  }
183}
184
185impl<'read, 'parent, R: Read<'read>, S: Stack> FieldIterator<'read, 'parent, R, S> {
186  /// The next field within the object.
187  ///
188  /// This is approximate to `Iterator::next` yet each item maintains a mutable reference to the
189  /// iterator. Accordingly, we cannot use `Iterator::next` which requires items not borrow from
190  /// the iterator.
191  ///
192  /// [polonius-the-crab](https://docs.rs/polonius-the-crab) details a frequent limitation of
193  /// Rust's borrow checker which users of this function may incur. It also details potential
194  /// solutions (primarily using inlined code instead of functions, callbacks) before presenting
195  /// itself as a complete solution. Please refer to it if you have difficulties calling this
196  /// method for context.
197  #[allow(clippy::type_complexity, clippy::should_implement_trait)]
198  pub fn next(&mut self) -> Option<Result<Field<'read, '_, R, S>, JsonError<'read, R, S>>> {
199    if let Some(err) = self.deserializer.error {
200      return Some(Err(err));
201    }
202
203    if self.done {
204      None?;
205    }
206
207    loop {
208      let result = match self.deserializer.single_step() {
209        Ok(SingleStepResult::Object(result)) => result,
210        Ok(_) => break Some(Err(JsonError::InternalError)),
211        Err(e) => break Some(Err(e)),
212      };
213      match result {
214        SingleStepObjectResult::Field => break Some(Ok(handle_field(self.deserializer))),
215        SingleStepObjectResult::Closed => {
216          self.done = true;
217          None?
218        }
219      }
220    }
221  }
222}
223
224/// An iterator over an array.
225pub struct ArrayIterator<'read, 'parent, R: Read<'read>, S: Stack> {
226  deserializer: &'parent mut Deserializer<'read, R, S>,
227  done: bool,
228}
229
230// When this array is dropped, advance the decoder past the unread items
231impl<'read, 'parent, R: Read<'read>, S: Stack> Drop for ArrayIterator<'read, 'parent, R, S> {
232  #[inline(always)]
233  fn drop(&mut self) {
234    if self.deserializer.error.is_some() {
235      return;
236    }
237
238    loop {
239      let Some(next) = self.next() else { break };
240      let next = next.map(|_| ());
241      match next {
242        Ok(()) => {}
243        Err(e) => {
244          self.deserializer.error = Some(e);
245          break;
246        }
247      }
248    }
249  }
250}
251
252impl<'read, 'parent, R: Read<'read>, S: Stack> ArrayIterator<'read, 'parent, R, S> {
253  /// The next item within the array.
254  ///
255  /// This is approximate to `Iterator::next` yet each item maintains a mutable reference to the
256  /// iterator. Accordingly, we cannot use `Iterator::next` which requires items not borrow from
257  /// the iterator.
258  ///
259  /// [polonius-the-crab](https://docs.rs/polonius-the-crab) details a frequent limitation of
260  /// Rust's borrow checker which users of this function may incur. It also details potential
261  /// solutions (primarily using inlined code instead of functions, callbacks) before presenting
262  /// itself as a complete solution. Please refer to it if you have difficulties calling this
263  /// method for context.
264  #[allow(clippy::should_implement_trait)]
265  pub fn next(&mut self) -> Option<Result<Value<'read, '_, R, S>, JsonError<'read, R, S>>> {
266    if let Some(err) = self.deserializer.error {
267      return Some(Err(err));
268    }
269
270    if self.done {
271      None?;
272    }
273
274    loop {
275      let result = match self.deserializer.single_step() {
276        Ok(SingleStepResult::Array(result)) => result,
277        Ok(_) => break Some(Err(JsonError::InternalError)),
278        Err(e) => break Some(Err(e)),
279      };
280      match result {
281        SingleStepArrayResult::Value => {
282          break Some(Ok(Value { deserializer: Some(self.deserializer) }))
283        }
284        SingleStepArrayResult::Closed => {
285          self.done = true;
286          None?
287        }
288      }
289    }
290  }
291}
292
293impl<'read, 'parent, R: Read<'read>, S: Stack> Value<'read, 'parent, R, S> {
294  /// Get the type of the current item.
295  ///
296  /// This does not assert it's a valid instance of this class of items. It solely asserts if this
297  /// is a valid item, it will be of this type.
298  #[inline(always)]
299  pub fn kind(&mut self) -> Result<Type, JsonError<'read, R, S>> {
300    Ok(kind(&self.deserializer.as_ref().ok_or(JsonError::InternalError)?.reader))
301  }
302
303  /// Iterate over the fields within this object.
304  ///
305  /// If a field is present multiple times, this will yield each instance.
306  #[inline(always)]
307  pub fn fields(mut self) -> Result<FieldIterator<'read, 'parent, R, S>, JsonError<'read, R, S>> {
308    if !matches!(self.kind()?, Type::Object) {
309      Err(JsonError::TypeError)?
310    }
311
312    let deserializer = self.deserializer.take().ok_or(JsonError::InternalError)?;
313    match deserializer.single_step()? {
314      SingleStepResult::Unknown(SingleStepUnknownResult::ObjectOpened) => {
315        Ok(FieldIterator { deserializer, done: false })
316      }
317      _ => Err(JsonError::InternalError),
318    }
319  }
320
321  /// Iterate over all items within this container.
322  #[inline(always)]
323  pub fn iterate(mut self) -> Result<ArrayIterator<'read, 'parent, R, S>, JsonError<'read, R, S>> {
324    if !matches!(self.kind()?, Type::Array) {
325      Err(JsonError::TypeError)?
326    }
327
328    let deserializer = self.deserializer.take().ok_or(JsonError::InternalError)?;
329    match deserializer.single_step()? {
330      SingleStepResult::Unknown(SingleStepUnknownResult::ArrayOpened) => {
331        Ok(ArrayIterator { deserializer, done: false })
332      }
333      _ => Err(JsonError::InternalError),
334    }
335  }
336
337  /// Get the current item as a 'string'.
338  ///
339  /// As we cannot perform allocations, we do not yield a [`alloc::string::String`] but rather an
340  /// iterator for the contents of the serialized string (with its escape sequences handled). This
341  /// may be converted to an `String` with `.collect::<Result<String, _>>()?`.
342  ///
343  /// RFC 8259 allows strings to specify invalid UTF-8 codepoints. This library supports working
344  /// with such values, as required to be compliant with RFC 8259, but this function's return value
345  /// will error when attempting to return a non-UTF-8 value. If the underlying JSON is valid, the
346  /// deserializer will remain usable afterwards however, even though the rest of the non-UTF-8
347  /// string will be inaccesible. Please keep this detail in mind.
348  #[inline(always)]
349  pub fn to_str(
350    mut self,
351  ) -> Result<
352    impl use<'read, 'parent, R, S> + Iterator<Item = Result<char, JsonError<'read, R, S>>>,
353    JsonError<'read, R, S>,
354  > {
355    if !matches!(self.kind()?, Type::String) {
356      Err(JsonError::TypeError)?
357    }
358
359    let deserializer = self.deserializer.take().ok_or(JsonError::InternalError)?;
360    match deserializer.single_step()? {
361      SingleStepResult::Unknown(SingleStepUnknownResult::String) => {
362        Ok(handle_string_value(deserializer))
363      }
364      _ => Err(JsonError::InternalError),
365    }
366  }
367
368  /// Get the current item as a number.
369  #[inline(always)]
370  pub fn to_number(mut self) -> Result<Number, JsonError<'read, R, S>> {
371    if !matches!(self.kind()?, Type::Number) {
372      Err(JsonError::TypeError)?
373    }
374
375    let deserializer = self.deserializer.take().ok_or(JsonError::InternalError)?;
376    match deserializer.single_step()? {
377      SingleStepResult::Unknown(SingleStepUnknownResult::Number(number)) => Ok(number),
378      _ => Err(JsonError::InternalError),
379    }
380  }
381
382  /// Get the current item as a `bool`.
383  #[inline(always)]
384  pub fn to_bool(mut self) -> Result<bool, JsonError<'read, R, S>> {
385    if !matches!(self.kind()?, Type::Bool) {
386      Err(JsonError::TypeError)?
387    }
388
389    let deserializer = self.deserializer.take().ok_or(JsonError::InternalError)?;
390    match deserializer.single_step()? {
391      SingleStepResult::Unknown(SingleStepUnknownResult::Bool(bool)) => Ok(bool),
392      _ => Err(JsonError::InternalError),
393    }
394  }
395
396  /// Get the current item as `null`.
397  ///
398  /// The point of this method is to assert the value is `null` _and valid_. `kind` only tells the
399  /// caller if it's a valid value, it will be `null`.
400  #[inline(always)]
401  pub fn to_null(mut self) -> Result<(), JsonError<'read, R, S>> {
402    if !matches!(self.kind()?, Type::Null) {
403      Err(JsonError::TypeError)?
404    }
405
406    let deserializer = self.deserializer.take().ok_or(JsonError::InternalError)?;
407    match deserializer.single_step()? {
408      SingleStepResult::Unknown(SingleStepUnknownResult::Null) => Ok(()),
409      _ => Err(JsonError::InternalError),
410    }
411  }
412}