Skip to main content

sark_json/
parsing.rs

1//! JSON decoding contracts.
2
3use std::num::NonZero;
4
5use o3::buffer::storage;
6
7use crate::writing;
8
9/// Remaining containers below the current typed object; the root object is excluded.
10#[derive(Clone, Copy, Debug)]
11pub struct Depth(u8);
12
13impl Depth {
14    pub const ROOT: Self = Self(crate::nesting::MAX_DEPTH as u8);
15
16    pub fn child(self) -> crate::Result<Self> {
17        Ok(Self(self.nonzero()?.get() - 1))
18    }
19
20    pub(crate) fn nonzero(self) -> crate::Result<NonZero<u8>> {
21        NonZero::new(self.0).ok_or(crate::Error::Depth)
22    }
23}
24
25#[derive(Debug)]
26pub enum Error<'a> {
27    Parse(crate::Error),
28    Missing(&'a str),
29}
30
31impl From<crate::Error> for Error<'_> {
32    fn from(error: crate::Error) -> Self {
33        Self::Parse(error)
34    }
35}
36
37pub trait Decode: Sized {
38    fn decode<'a>(input: storage::Shared) -> Result<Self, Error<'a>>;
39
40    fn decode_ref<'a>(input: &'a [u8]) -> Result<Self, Error<'a>> {
41        let input = storage::Shared::try_copy(input).map_err(crate::Error::from)?;
42        Self::decode(input)
43    }
44}
45
46/// Decodes a request-scoped view without copying the complete JSON body.
47pub trait Request {
48    type View<'req>: writing::TryEncode;
49
50    fn decode<'req>(input: &'req [u8]) -> Result<Self::View<'req>, Error<'req>> {
51        let (view, mut index) = Self::prefix(input, 0, Depth::ROOT)?;
52        crate::input::Input::finish(input, &mut index)?;
53        Ok(view)
54    }
55
56    /// Decodes one object prefix using the budget below that object.
57    /// Callers entering a nested object must first consume [`Depth::child`].
58    #[doc(hidden)]
59    fn prefix<'req>(
60        input: &'req [u8],
61        index: usize,
62        depth: Depth,
63    ) -> Result<(Self::View<'req>, usize), Error<'req>>;
64}