musli_json/de/
object_decoder.rs

1use core::mem::{replace, take};
2
3use musli::de::{Decoder, EntriesDecoder, EntryDecoder, MapDecoder, SizeHint};
4use musli::Context;
5
6use crate::parser::{Parser, Token};
7
8use super::{JsonDecoder, JsonKeyDecoder, JsonObjectPairDecoder};
9
10#[must_use = "Must call skip_object_remaining to complete decoding"]
11pub(crate) struct JsonObjectDecoder<'a, P, C: ?Sized> {
12    cx: &'a C,
13    first: bool,
14    len: Option<usize>,
15    parser: P,
16    finalized: bool,
17}
18
19impl<'a, 'de, P, C> JsonObjectDecoder<'a, P, C>
20where
21    P: Parser<'de>,
22    C: ?Sized + Context,
23{
24    pub(super) fn new_in(
25        cx: &'a C,
26        first: bool,
27        len: Option<usize>,
28        parser: P,
29    ) -> Result<Self, C::Error> {
30        Ok(Self {
31            cx,
32            first,
33            len,
34            parser,
35            finalized: false,
36        })
37    }
38
39    #[inline]
40    pub(super) fn new(cx: &'a C, len: Option<usize>, mut parser: P) -> Result<Self, C::Error> {
41        let actual = parser.peek(cx)?;
42
43        if !matches!(actual, Token::OpenBrace) {
44            return Err(cx.message(format_args!("Expected opening brace, was {actual}")));
45        }
46
47        parser.skip(cx, 1)?;
48
49        Ok(Self {
50            cx,
51            first: true,
52            len,
53            parser,
54            finalized: false,
55        })
56    }
57
58    fn parse_map_key(&mut self) -> Result<bool, C::Error> {
59        if self.finalized {
60            return Ok(false);
61        }
62
63        let first = take(&mut self.first);
64
65        loop {
66            let token = self.parser.peek(self.cx)?;
67
68            match token {
69                Token::String => {
70                    return Ok(true);
71                }
72                Token::Comma if !first => {
73                    self.parser.skip(self.cx, 1)?;
74                }
75                Token::CloseBrace => {
76                    return Ok(false);
77                }
78                token => {
79                    return Err(self.cx.message(format_args!(
80                        "Expected value, or closing brace `}}` but found {token:?}"
81                    )));
82                }
83            }
84        }
85    }
86
87    /// Parse end of object.
88    #[inline]
89    pub(super) fn skip_object_remaining(mut self) -> Result<(), C::Error> {
90        // Someone else is responsible for finalizing this decoder.
91        if self.finalized {
92            return Ok(());
93        }
94
95        while let Some(mut entry) = self.decode_entry()? {
96            entry.decode_key()?.skip()?;
97            entry.decode_value()?.skip()?;
98        }
99
100        let actual = self.parser.peek(self.cx)?;
101
102        if !matches!(actual, Token::CloseBrace) {
103            return Err(self
104                .cx
105                .message(format_args!("Expected closing brace `}}`, was {actual}")));
106        }
107
108        self.parser.skip(self.cx, 1)?;
109        self.finalized = true;
110        Ok(())
111    }
112}
113
114impl<'a, 'de, P, C> MapDecoder<'de> for JsonObjectDecoder<'a, P, C>
115where
116    P: Parser<'de>,
117    C: ?Sized + Context,
118{
119    type Cx = C;
120    type DecodeEntry<'this> = JsonObjectPairDecoder<'a, P::Mut<'this>, C>
121    where
122        Self: 'this;
123    type DecodeRemainingEntries<'this> = JsonObjectDecoder<'a, P::Mut<'this>, C>
124    where
125        Self: 'this;
126
127    #[inline]
128    fn size_hint(&self) -> SizeHint {
129        SizeHint::from(self.len)
130    }
131
132    #[inline]
133    fn decode_entry(&mut self) -> Result<Option<Self::DecodeEntry<'_>>, C::Error> {
134        if !self.parse_map_key()? {
135            return Ok(None);
136        }
137
138        Ok(Some(JsonObjectPairDecoder::new(
139            self.cx,
140            self.parser.borrow_mut(),
141        )))
142    }
143
144    #[inline]
145    fn decode_remaining_entries(
146        &mut self,
147    ) -> Result<Self::DecodeRemainingEntries<'_>, <Self::Cx as Context>::Error> {
148        if replace(&mut self.finalized, true) {
149            return Err(self
150                .cx
151                .message("Cannot decode remaining entries after finalizing"));
152        }
153
154        JsonObjectDecoder::new_in(self.cx, self.first, self.len, self.parser.borrow_mut())
155    }
156}
157
158impl<'a, 'de, P, C> EntriesDecoder<'de> for JsonObjectDecoder<'a, P, C>
159where
160    P: Parser<'de>,
161    C: ?Sized + Context,
162{
163    type Cx = C;
164    type DecodeEntryKey<'this> = JsonKeyDecoder<'a, P::Mut<'this>, C>
165    where
166        Self: 'this;
167    type DecodeEntryValue<'this> = JsonDecoder<'a, P::Mut<'this>, C> where Self: 'this;
168
169    #[inline]
170    fn decode_entry_key(&mut self) -> Result<Option<Self::DecodeEntryKey<'_>>, C::Error> {
171        if !self.parse_map_key()? {
172            return Ok(None);
173        }
174
175        Ok(Some(JsonKeyDecoder::new(self.cx, self.parser.borrow_mut())))
176    }
177
178    #[inline]
179    fn decode_entry_value(&mut self) -> Result<Self::DecodeEntryValue<'_>, C::Error> {
180        let actual = self.parser.peek(self.cx)?;
181
182        if !matches!(actual, Token::Colon) {
183            return Err(self
184                .cx
185                .message(format_args!("Expected colon `:`, was {actual}")));
186        }
187
188        self.parser.skip(self.cx, 1)?;
189        Ok(JsonDecoder::new(self.cx, self.parser.borrow_mut()))
190    }
191
192    #[inline]
193    fn end_entries(self) -> Result<(), C::Error> {
194        self.skip_object_remaining()
195    }
196}