core_json/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![deny(missing_docs)]
4#![no_std]
5
6#[cfg(feature = "alloc")]
7extern crate alloc;
8
9mod io;
10mod stack;
11mod string;
12mod number;
13
14pub(crate) use io::*;
15pub use io::BytesLike;
16pub use stack::*;
17use string::*;
18
19/// An error incurred when deserializing.
20#[derive(Debug)]
21pub enum JsonError<'bytes, B: BytesLike<'bytes>, S: Stack> {
22  /// An unexpected state was reached during deserialization.
23  InternalError,
24  /// An error from the bytes.
25  BytesError(B::Error),
26  /// An error from the stack.
27  StackError(S::Error),
28  /// The deserializer was reused.
29  ReusedDeserializer,
30  /// The JSON had an invalid key.
31  InvalidKey,
32  /// The JSON had an invalid delimiter between the key and value (`:` expected).
33  InvalidKeyValueDelimiter,
34  /// The JSON had an invalid value.
35  InvalidValue,
36  /// The JSON had a trailing comma.
37  TrailingComma,
38  /// The JSON had mismatched delimiters between the open and close of the structure.
39  MismatchedDelimiter,
40  /// Operation could not be performed given the value's type.
41  TypeError,
42}
43impl<'bytes, B: BytesLike<'bytes>, S: Stack> Clone for JsonError<'bytes, B, S> {
44  #[inline(always)]
45  fn clone(&self) -> Self {
46    *self
47  }
48}
49impl<'bytes, B: BytesLike<'bytes>, S: Stack> Copy for JsonError<'bytes, B, S> {}
50
51/// Interpret the immediate value within the bytes as a `bool`.
52#[inline(always)]
53pub fn as_bool<'bytes, B: BytesLike<'bytes>, S: Stack>(
54  bytes: &B,
55) -> Result<bool, JsonError<'bytes, B, S>> {
56  let first = bytes.peek(0).map_err(JsonError::BytesError)?;
57  // Return early if this definitely isn't a valid `bool`
58  if !matches!(first, b't' | b'f') {
59    Err(JsonError::TypeError)?;
60  }
61  let second = bytes.peek(1).map_err(JsonError::BytesError)?;
62  let third = bytes.peek(2).map_err(JsonError::BytesError)?;
63  let fourth = bytes.peek(3).map_err(JsonError::BytesError)?;
64  let fifth = bytes.peek(4).map_err(JsonError::BytesError)?;
65
66  let is_true = (first, second, third, fourth) == (b't', b'r', b'u', b'e');
67  let is_false = (first, second, third, fourth, fifth) == (b'f', b'a', b'l', b's', b'e');
68
69  if !(is_true || is_false) {
70    Err(JsonError::TypeError)?;
71  }
72
73  Ok(is_true)
74}
75
76/// Check if the immediate value within the bytes is `null`.
77#[inline(always)]
78pub fn is_null<'bytes, B: BytesLike<'bytes>, S: Stack>(
79  bytes: &B,
80) -> Result<bool, JsonError<'bytes, B, S>> {
81  let first = bytes.peek(0).map_err(JsonError::BytesError)?;
82  if first != b'n' {
83    return Ok(false);
84  }
85  let second = bytes.peek(1).map_err(JsonError::BytesError)?;
86  let third = bytes.peek(2).map_err(JsonError::BytesError)?;
87  let fourth = bytes.peek(3).map_err(JsonError::BytesError)?;
88
89  if (second, third, fourth) != (b'u', b'l', b'l') {
90    Err(JsonError::InvalidValue)?;
91  }
92  Ok(true)
93}
94
95/// Advance the bytes until there's a non-whitespace character.
96#[inline(always)]
97fn advance_whitespace<'bytes, B: BytesLike<'bytes>, S: Stack>(
98  bytes: &mut B,
99) -> Result<(), JsonError<'bytes, B, S>> {
100  loop {
101    let next = bytes.peek(0).map_err(JsonError::BytesError)?;
102    // https://datatracker.ietf.org/doc/html/rfc8259#section-2 defines whitespace as follows
103    if !matches!(next, b'\x20' | b'\x09' | b'\x0A' | b'\x0D') {
104      break;
105    }
106    bytes.advance(1).map_err(JsonError::BytesError)?;
107  }
108  Ok(())
109}
110
111/// Advance past a comma, or to the close of the structure.
112fn advance_past_comma_or_to_close<'bytes, B: BytesLike<'bytes>, S: Stack>(
113  bytes: &mut B,
114) -> Result<(), JsonError<'bytes, B, S>> {
115  advance_whitespace(bytes)?;
116  match bytes.peek(0).map_err(JsonError::BytesError)? {
117    b',' => {
118      bytes.advance(1).map_err(JsonError::BytesError)?;
119      advance_whitespace(bytes)?;
120      if matches!(bytes.peek(0).map_err(JsonError::BytesError)?, b']' | b'}') {
121        Err(JsonError::TrailingComma)?;
122      }
123    }
124    b']' | b'}' => {}
125    _ => Err(JsonError::InvalidValue)?,
126  }
127  Ok(())
128}
129
130/// The result from a single step of the deserialized, if within an object.
131enum SingleStepObjectResult<'bytes, B: BytesLike<'bytes>> {
132  /// A field within the object was advanced to.
133  Field {
134    /// The key for this field.
135    key: String<'bytes, B>,
136  },
137  /// The object was closed.
138  Closed,
139}
140
141/// The result from a single step of the deserialized, if within an array.
142enum SingleStepArrayResult {
143  /// A value within the array was advanced to.
144  Value,
145  /// The array was closed.
146  Closed,
147}
148
149/// The result from a single step of the deserializer, if handling an unknown value.
150enum SingleStepUnknownResult<'bytes, B: BytesLike<'bytes>> {
151  /// An object was opened.
152  ObjectOpened,
153  /// An array was opened.
154  ArrayOpened,
155  /// A string was read.
156  String(String<'bytes, B>),
157  /// A unit value was advanced past.
158  Advanced,
159}
160
161/// The result from a single step of the deserializer.
162enum SingleStepResult<'bytes, B: BytesLike<'bytes>> {
163  /// The result if within an object.
164  Object(SingleStepObjectResult<'bytes, B>),
165  /// The result if within an array.
166  Array(SingleStepArrayResult),
167  /// The result if handling an unknown value.
168  Unknown(SingleStepUnknownResult<'bytes, B>),
169}
170
171/// Step the deserializer forwards.
172///
173/// This assumes there is no leading whitespace present in `bytes` and will advance past any
174/// whitespace present before the next logical unit.
175fn single_step<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack>(
176  bytes: &'parent mut B,
177  stack: &'parent mut S,
178) -> Result<SingleStepResult<'bytes, B>, JsonError<'bytes, B, S>> {
179  match stack.peek().ok_or(JsonError::InternalError)? {
180    State::Object => {
181      let next = bytes.read_byte().map_err(JsonError::BytesError)?;
182
183      // Check if the object terminates
184      if next == b'}' {
185        stack.pop().ok_or(JsonError::InternalError)?;
186
187        // If this isn't the outer object, advance past the comma after
188        if stack.depth() != 0 {
189          advance_past_comma_or_to_close(bytes)?;
190        }
191
192        return Ok(SingleStepResult::Object(SingleStepObjectResult::Closed));
193      }
194
195      // Read the name of this field
196      if next != b'"' {
197        Err(JsonError::InvalidKey)?;
198      }
199      let key = read_string(bytes)?;
200
201      // Read the colon delimiter
202      advance_whitespace::<_, S>(bytes)?;
203      if bytes.read_byte().map_err(JsonError::BytesError)? != b':' {
204        Err(JsonError::InvalidKeyValueDelimiter)?;
205      }
206
207      // Push how we're reading a value of an unknown type onto the stack
208      advance_whitespace::<_, S>(bytes)?;
209      stack.push(State::Unknown).map_err(JsonError::StackError)?;
210      Ok(SingleStepResult::Object(SingleStepObjectResult::Field { key }))
211    }
212    State::Array => {
213      // Check if the array terminates
214      if bytes.peek(0).map_err(JsonError::BytesError)? == b']' {
215        stack.pop().ok_or(JsonError::InternalError)?;
216        bytes.advance(1).map_err(JsonError::BytesError)?;
217
218        // If this isn't the outer object, advance past the comma after
219        if stack.depth() != 0 {
220          advance_past_comma_or_to_close(bytes)?;
221        }
222
223        return Ok(SingleStepResult::Array(SingleStepArrayResult::Closed));
224      }
225
226      // Since the array doesn't terminate, read the next value
227      stack.push(State::Unknown).map_err(JsonError::StackError)?;
228      Ok(SingleStepResult::Array(SingleStepArrayResult::Value))
229    }
230    State::Unknown => {
231      stack.pop().ok_or(JsonError::InternalError)?;
232
233      let mut result = SingleStepResult::Unknown(SingleStepUnknownResult::Advanced);
234      match bytes.peek(0).map_err(JsonError::BytesError)? {
235        // Handle if this opens an object
236        b'{' => {
237          bytes.advance(1).map_err(JsonError::BytesError)?;
238          advance_whitespace(bytes)?;
239          stack.push(State::Object).map_err(JsonError::StackError)?;
240          return Ok(SingleStepResult::Unknown(SingleStepUnknownResult::ObjectOpened));
241        }
242        // Handle if this opens an array
243        b'[' => {
244          bytes.advance(1).map_err(JsonError::BytesError)?;
245          advance_whitespace(bytes)?;
246          stack.push(State::Array).map_err(JsonError::StackError)?;
247          return Ok(SingleStepResult::Unknown(SingleStepUnknownResult::ArrayOpened));
248        }
249        // Handle if this opens an string
250        b'"' => {
251          bytes.advance(1).map_err(JsonError::BytesError)?;
252          // Read past the string
253          result = SingleStepResult::Unknown(SingleStepUnknownResult::String(read_string(bytes)?));
254        }
255        // This is a distinct unit value
256        _ => {
257          // https://datatracker.ietf.org/doc/html/rfc8259#section-3 defines all possible values
258          let is_number = match number::is_number_str(bytes) {
259            Ok(len) => Some(len),
260            Err(JsonError::TypeError) => None,
261            Err(e) => Err(e)?,
262          };
263          let is_bool = match as_bool(bytes) {
264            Ok(value) => Some(if value { 4 } else { 5 }),
265            Err(JsonError::TypeError) => None,
266            Err(e) => Err(e)?,
267          };
268          let is_null = match is_null(bytes) {
269            Ok(is_null) => {
270              if is_null {
271                Some(4)
272              } else {
273                None
274              }
275            }
276            Err(e) => Err(e)?,
277          };
278
279          if let Some(len) = is_number.or(is_bool).or(is_null) {
280            bytes.advance(len).map_err(JsonError::BytesError)?;
281          } else {
282            Err(JsonError::InvalidValue)?;
283          }
284        }
285      }
286
287      // We now have to read past the next comma, or to the next closing of a structure
288      advance_past_comma_or_to_close(bytes)?;
289
290      Ok(result)
291    }
292  }
293}
294
295/// A deserializer for a JSON-encoded structure.
296pub struct Deserializer<'bytes, B: BytesLike<'bytes>, S: Stack> {
297  bytes: B,
298  stack: S,
299  /*
300    We advance the deserializer within `Drop` which cannot return an error. If an error is raised
301    within drop, we store it here to be consumed upon the next call to a method which can return an
302    error (if one is ever called).
303  */
304  error: Option<JsonError<'bytes, B, S>>,
305}
306
307/// A JSON value.
308// Internally, we assume whenever this is held, the top item on the stack is `State::Unknown`
309pub struct Value<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack> {
310  deserializer: Option<&'parent mut Deserializer<'bytes, B, S>>,
311}
312
313impl<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack> Drop for Value<'bytes, 'parent, B, S> {
314  fn drop(&mut self) {
315    /*
316      When this value is dropped, we advance the deserializer past it if it hasn't already been
317      converted into a `FieldIterator` or `ArrayIterator` (which each have their own `Drop`
318      implementations).
319    */
320    if let Some(deserializer) = self.deserializer.take() {
321      if deserializer.error.is_some() {
322        return;
323      }
324
325      let Some(current) = deserializer.stack.peek() else {
326        deserializer.error = Some(JsonError::InternalError);
327        return;
328      };
329
330      let mut depth = match current {
331        State::Object | State::Array => 1,
332        State::Unknown => {
333          let step = match single_step(&mut deserializer.bytes, &mut deserializer.stack) {
334            Ok(SingleStepResult::Unknown(step)) => step,
335            Ok(_) => {
336              deserializer.error = Some(JsonError::InternalError);
337              return;
338            }
339            Err(e) => {
340              deserializer.error = Some(e);
341              return;
342            }
343          };
344          match step {
345            // We successfully advanced past this item
346            SingleStepUnknownResult::String(_) | SingleStepUnknownResult::Advanced => return,
347            // We opened an object/array we now have to advance past
348            SingleStepUnknownResult::ObjectOpened | SingleStepUnknownResult::ArrayOpened => 1,
349          }
350        }
351      };
352
353      // Since our object isn't a unit, step the deserializer until it's advanced past
354      while depth != 0 {
355        let step = match single_step(&mut deserializer.bytes, &mut deserializer.stack) {
356          Ok(step) => step,
357          Err(e) => {
358            deserializer.error = Some(e);
359            return;
360          }
361        };
362        match step {
363          SingleStepResult::Object(SingleStepObjectResult::Closed) |
364          SingleStepResult::Array(SingleStepArrayResult::Closed) => depth -= 1,
365          SingleStepResult::Unknown(
366            SingleStepUnknownResult::ObjectOpened | SingleStepUnknownResult::ArrayOpened,
367          ) => depth += 1,
368          _ => {}
369        }
370      }
371    }
372  }
373}
374
375impl<'bytes, B: BytesLike<'bytes>, S: Stack> Deserializer<'bytes, B, S> {
376  /// Create a new deserializer.
377  pub fn new(mut bytes: B) -> Result<Self, JsonError<'bytes, B, S>> {
378    advance_whitespace(&mut bytes)?;
379
380    let mut stack = S::empty();
381    stack.push(State::Unknown).map_err(JsonError::StackError)?;
382
383    Ok(Deserializer { bytes, stack, error: None })
384  }
385
386  /// Obtain the `Value` representing the serialized structure.
387  ///
388  /// This takes a mutable reference as `Deserializer` is the owned object representing the
389  /// deserializer's state. However, this is not eligible to be called more than once, even after
390  /// the initial mutable borrow is dropped. Multiple calls to this function will cause an error to
391  /// be returned.
392  #[inline(always)]
393  pub fn value(&mut self) -> Result<Value<'bytes, '_, B, S>, JsonError<'bytes, B, S>> {
394    if self.stack.depth() != 1 {
395      Err(JsonError::ReusedDeserializer)?;
396    }
397    let result = Value { deserializer: Some(self) };
398    if !(result.is_object()? || result.is_array()?) {
399      Err(JsonError::TypeError)?;
400    }
401    Ok(result)
402  }
403}
404
405/// An iterator over fields.
406pub struct FieldIterator<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack> {
407  deserializer: &'parent mut Deserializer<'bytes, B, S>,
408  done: bool,
409}
410
411// When this object is dropped, advance the decoder past the unread items
412impl<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack> Drop
413  for FieldIterator<'bytes, 'parent, B, S>
414{
415  #[inline(always)]
416  fn drop(&mut self) {
417    if self.deserializer.error.is_some() {
418      return;
419    }
420
421    loop {
422      let Some(next) = self.next() else { break };
423      let next = next.map(|_| ());
424      match next {
425        Ok(()) => {}
426        Err(e) => {
427          self.deserializer.error = Some(e);
428          break;
429        }
430      }
431    }
432  }
433}
434
435impl<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack> FieldIterator<'bytes, 'parent, B, S> {
436  /// The next entry (key, value) within the object.
437  ///
438  /// The key is presented as an iterator over the characters within the serialized string, with
439  /// the escape sequences handled. If the key specifies invalid UTF characters, the iterator will
440  /// yield an error when it attempts to parse them. While it may not be possible to parse a key
441  /// as UTF characters, decoding of this field's value (and the rest of the structure) is still
442  /// possible (even _after_ the iterator yields its error). For more information, please refer to
443  /// [`Value::to_str`].
444  ///
445  /// This is approximate to `Iterator::next` yet each item maintains a mutable reference to the
446  /// iterator. Accordingly, we cannot use `Iterator::next` which requires items not borrow from
447  /// the iterator.
448  ///
449  /// [polonius-the-crab](https://docs.rs/polonius-the-crab) details a frequent limitation of
450  /// Rust's borrow checker which users of this function may incur. It also details potential
451  /// solutions (primarily using inlined code instead of functions, callbacks) before presenting
452  /// itself as a complete solution. Please refer to it if you have difficulties calling this
453  /// method for context.
454  #[allow(clippy::type_complexity, clippy::should_implement_trait)]
455  pub fn next(
456    &mut self,
457  ) -> Option<
458    Result<
459      (
460        impl use<'bytes, B, S> + Iterator<Item = Result<char, JsonError<'bytes, B, S>>>,
461        Value<'bytes, '_, B, S>,
462      ),
463      JsonError<'bytes, B, S>,
464    >,
465  > {
466    if let Some(err) = self.deserializer.error {
467      return Some(Err(err));
468    }
469
470    if self.done {
471      None?;
472    }
473
474    loop {
475      let result = match single_step(&mut self.deserializer.bytes, &mut self.deserializer.stack) {
476        Ok(SingleStepResult::Object(result)) => result,
477        Ok(_) => break Some(Err(JsonError::InternalError)),
478        Err(e) => break Some(Err(e)),
479      };
480      match result {
481        SingleStepObjectResult::Field { key } => {
482          break Some(Ok((
483            UnescapeString::from(key),
484            Value { deserializer: Some(self.deserializer) },
485          )))
486        }
487        SingleStepObjectResult::Closed => {
488          self.done = true;
489          None?
490        }
491      }
492    }
493  }
494}
495
496/// An iterator over an array.
497pub struct ArrayIterator<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack> {
498  deserializer: &'parent mut Deserializer<'bytes, B, S>,
499  done: bool,
500}
501
502// When this array is dropped, advance the decoder past the unread items
503impl<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack> Drop
504  for ArrayIterator<'bytes, 'parent, B, S>
505{
506  #[inline(always)]
507  fn drop(&mut self) {
508    if self.deserializer.error.is_some() {
509      return;
510    }
511
512    loop {
513      let Some(next) = self.next() else { break };
514      let next = next.map(|_| ());
515      match next {
516        Ok(()) => {}
517        Err(e) => {
518          self.deserializer.error = Some(e);
519          break;
520        }
521      }
522    }
523  }
524}
525
526impl<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack> ArrayIterator<'bytes, 'parent, B, S> {
527  /// The next item within the array.
528  ///
529  /// This is approximate to `Iterator::next` yet each item maintains a mutable reference to the
530  /// iterator. Accordingly, we cannot use `Iterator::next` which requires items not borrow from
531  /// the iterator.
532  ///
533  /// [polonius-the-crab](https://docs.rs/polonius-the-crab) details a frequent limitation of
534  /// Rust's borrow checker which users of this function may incur. It also details potential
535  /// solutions (primarily using inlined code instead of functions, callbacks) before presenting
536  /// itself as a complete solution. Please refer to it if you have difficulties calling this
537  /// method for context.
538  #[allow(clippy::should_implement_trait)]
539  pub fn next(&mut self) -> Option<Result<Value<'bytes, '_, B, S>, JsonError<'bytes, B, S>>> {
540    if let Some(err) = self.deserializer.error {
541      return Some(Err(err));
542    }
543
544    if self.done {
545      None?;
546    }
547
548    loop {
549      let result = match single_step(&mut self.deserializer.bytes, &mut self.deserializer.stack) {
550        Ok(SingleStepResult::Array(result)) => result,
551        Ok(_) => break Some(Err(JsonError::InternalError)),
552        Err(e) => break Some(Err(e)),
553      };
554      match result {
555        SingleStepArrayResult::Value => {
556          break Some(Ok(Value { deserializer: Some(self.deserializer) }))
557        }
558        SingleStepArrayResult::Closed => {
559          self.done = true;
560          None?
561        }
562      }
563    }
564  }
565}
566
567impl<'bytes, 'parent, B: BytesLike<'bytes>, S: Stack> Value<'bytes, 'parent, B, S> {
568  /// Check if the current item is an object.
569  #[inline(always)]
570  pub fn is_object(&self) -> Result<bool, JsonError<'bytes, B, S>> {
571    Ok(
572      self
573        .deserializer
574        .as_ref()
575        .ok_or(JsonError::InternalError)?
576        .bytes
577        .peek(0)
578        .map_err(JsonError::BytesError)? ==
579        b'{',
580    )
581  }
582
583  /// Iterate over the fields within this object.
584  ///
585  /// If a field is present multiple times, this will yield each instance.
586  pub fn fields(mut self) -> Result<FieldIterator<'bytes, 'parent, B, S>, JsonError<'bytes, B, S>> {
587    let deserializer = self.deserializer.take().ok_or(JsonError::InternalError)?;
588    if let Some(err) = deserializer.error {
589      Err(err)?;
590    }
591
592    match single_step(&mut deserializer.bytes, &mut deserializer.stack)? {
593      SingleStepResult::Unknown(SingleStepUnknownResult::ObjectOpened) => {
594        Ok(FieldIterator { deserializer, done: false })
595      }
596      _ => Err(JsonError::TypeError),
597    }
598  }
599
600  /// Check if the current item is an array.
601  #[inline(always)]
602  pub fn is_array(&self) -> Result<bool, JsonError<'bytes, B, S>> {
603    Ok(
604      self
605        .deserializer
606        .as_ref()
607        .ok_or(JsonError::InternalError)?
608        .bytes
609        .peek(0)
610        .map_err(JsonError::BytesError)? ==
611        b'[',
612    )
613  }
614
615  /// Iterate over all items within this container.
616  pub fn iterate(
617    mut self,
618  ) -> Result<ArrayIterator<'bytes, 'parent, B, S>, JsonError<'bytes, B, S>> {
619    let deserializer = self.deserializer.take().ok_or(JsonError::InternalError)?;
620    if let Some(err) = deserializer.error {
621      Err(err)?;
622    }
623
624    match single_step(&mut deserializer.bytes, &mut deserializer.stack)? {
625      SingleStepResult::Unknown(SingleStepUnknownResult::ArrayOpened) => {
626        Ok(ArrayIterator { deserializer, done: false })
627      }
628      _ => Err(JsonError::TypeError),
629    }
630  }
631
632  /// Check if the current item is a string.
633  #[inline(always)]
634  pub fn is_str(&self) -> Result<bool, JsonError<'bytes, B, S>> {
635    Ok(
636      self
637        .deserializer
638        .as_ref()
639        .ok_or(JsonError::InternalError)?
640        .bytes
641        .peek(0)
642        .map_err(JsonError::BytesError)? ==
643        b'"',
644    )
645  }
646
647  /// Get the current item as a 'string'.
648  ///
649  /// As we cannot perform allocations, we do not yield a [`alloc::string::String`] but rather an
650  /// iterator for the contents of the serialized string (with its escape sequences handled). This
651  /// may be converted to an `String` with `.collect::<Result<String, _>>()?`.
652  ///
653  /// RFC 8259 allows strings to specify invalid UTF-8 codepoints. This library supports working
654  /// with such values, as required to be compliant with RFC 8259, but this function's return value
655  /// will error when attempting to return a non-UTF-8 value. Please keep this subtlety in mind.
656  #[inline(always)]
657  pub fn to_str(
658    mut self,
659  ) -> Result<
660    impl use<'bytes, B, S> + Iterator<Item = Result<char, JsonError<'bytes, B, S>>>,
661    JsonError<'bytes, B, S>,
662  > {
663    let deserializer = self.deserializer.take().ok_or(JsonError::InternalError)?;
664    match single_step(&mut deserializer.bytes, &mut deserializer.stack)? {
665      SingleStepResult::Unknown(SingleStepUnknownResult::String(str)) => {
666        Ok(UnescapeString::from(str))
667      }
668      _ => Err(JsonError::TypeError),
669    }
670  }
671
672  /// Get the current item as an `i64`.
673  ///
674  /// This uses the definition of a number defined in RFC 8259, then constrains it to having no
675  /// fractional, exponent parts. Then, it's yielded if it's representable within an `i64`.
676  ///
677  /// This is _exact_. It does not go through `f64` and does not experience its approximations.
678  #[inline(always)]
679  pub fn as_i64(&self) -> Result<i64, JsonError<'bytes, B, S>> {
680    let bytes = &self.deserializer.as_ref().ok_or(JsonError::InternalError)?.bytes;
681
682    // -9223372036854775808
683    const MAX_I64_LEN: usize = 20;
684    let len = number::is_number_str(bytes)?;
685    if len > MAX_I64_LEN {
686      Err(JsonError::TypeError)?;
687    }
688
689    let mut str = [0; MAX_I64_LEN];
690    #[allow(clippy::needless_range_loop)]
691    for i in 0 .. len {
692      let byte = bytes.peek(i).map_err(JsonError::BytesError)?;
693      if matches!(byte, b'.' | b'e' | b'E') {
694        Err(JsonError::TypeError)?;
695      }
696      str[i] = byte;
697    }
698    let str = core::str::from_utf8(&str[.. len]).map_err(|_| JsonError::InternalError)?;
699    <i64 as core::str::FromStr>::from_str(str).map_err(|_| JsonError::TypeError)
700  }
701
702  /// Get the current item as an `f64`.
703  ///
704  /// This may be lossy due to the inherent nature of floats combined with Rust's bounds on
705  /// precision.
706  pub fn as_f64(&self) -> Result<f64, JsonError<'bytes, B, S>> {
707    let bytes = &self.deserializer.as_ref().ok_or(JsonError::InternalError)?.bytes;
708
709    /*
710      The syntax for this (expanded) is
711      `[ minus ] int [ decimal-point 1*DIGIT ] [ e [ minus / plus ] 1*DIGIT ]`.
712
713      https://datatracker.ietf.org/doc/html/rfc8259#section-6 lets us specify the range, precision
714      of numbers.
715
716      We bind `minus`, `decimal-point`, `e`, `plus` to a maximum length of 1 as they definitively
717      have a length of 1. We bind the integer part to a maximum length of `f64::MAX_10_EXP + 1`,
718      the maximum length of a (sub)normal integer. We bind the fractional part to `f64::DIGITS`,
719      the amount of significant digits Rust can definitely convert back/forth with a base-10
720      serialization without loss of information. We bind the exponent to four digits as `f64` has
721      a maximum exponent `1000 < e < 2000`.
722    */
723    const MAX_DOUBLE_LEN: usize =
724      1 + ((f64::MAX_10_EXP as usize) + 1) + 1 + (f64::DIGITS as usize) + 1 + 1 + 4;
725    let len = number::is_number_str(bytes)?;
726
727    let mut src = 0;
728    let mut dst = 0;
729    let mut str = [0; MAX_DOUBLE_LEN];
730    let mut found_non_zero_digit = false;
731    let mut found_decimal = false;
732    let mut insignificant_digits = None;
733    #[allow(clippy::explicit_counter_loop)]
734    for i in 0 .. len {
735      let byte = bytes.peek(src).map_err(JsonError::BytesError)?;
736      src += 1;
737
738      /*
739        If we've found the leading digit, and this is within the decimal component, declare where
740        the insignificant digits begin.
741      */
742      if matches!(byte, b'1' ..= b'9') {
743        found_non_zero_digit = true;
744        if found_decimal {
745          insignificant_digits = i.checked_add(f64::DIGITS as usize - 1);
746        }
747      }
748
749      // If this is the opening of the fractional part, note the index it was opened at
750      if byte == b'.' {
751        found_decimal = true;
752        if found_non_zero_digit {
753          insignificant_digits = i.checked_add(f64::DIGITS as usize);
754        }
755      }
756
757      /*
758        If this is a fractional part with more significant digits than we can reasonably handle,
759        ignore the rest. This lets us handle serializations with greater precision, whose
760        serialization length exceeds our limit, so as long as the integer, exponent terms are
761        sufficiently bounded.
762      */
763      if let Some(insignificant_digits) = insignificant_digits {
764        if (i > insignificant_digits) && byte.is_ascii_digit() {
765          continue;
766        }
767      }
768
769      // If this an exponent, reset `insignificant_digits` so we start handling digits again
770      if matches!(byte, b'e' | b'E') {
771        insignificant_digits = None;
772      }
773
774      if dst == str.len() {
775        Err(JsonError::TypeError)?;
776      }
777      // Copy into the byte buffer for the string
778      str[dst] = byte;
779      dst += 1;
780    }
781    let str = core::str::from_utf8(&str[.. len]).map_err(|_| JsonError::InternalError)?;
782    <f64 as core::str::FromStr>::from_str(str).map_err(|_| JsonError::TypeError)
783  }
784
785  /// Get the current item as a `bool`.
786  #[inline(always)]
787  pub fn as_bool(&self) -> Result<bool, JsonError<'bytes, B, S>> {
788    as_bool(&self.deserializer.as_ref().ok_or(JsonError::InternalError)?.bytes)
789  }
790
791  /// Check if the current item is `null`.
792  #[inline(always)]
793  pub fn is_null(&self) -> Result<bool, JsonError<'bytes, B, S>> {
794    is_null(&self.deserializer.as_ref().ok_or(JsonError::InternalError)?.bytes)
795  }
796}