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 #[inline]
89 pub(super) fn skip_object_remaining(mut self) -> Result<(), C::Error> {
90 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}