1use docspec_core::{Error, Result};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Frame {
8 Array,
10 Object(KeyState),
12 Root,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum KeyState {
19 ExpectingKey,
21 ExpectingValue,
23}
24
25pub struct StateStack {
30 stack: Vec<Frame>,
31}
32
33impl StateStack {
34 #[inline]
36 #[must_use]
37 pub fn current(&self) -> Option<&Frame> {
38 self.stack.last()
39 }
40
41 #[inline]
47 pub fn expect_key_allowed(&self) -> Result<()> {
48 match self.stack.last() {
49 Some(Frame::Object(KeyState::ExpectingKey)) => Ok(()),
50 Some(Frame::Object(KeyState::ExpectingValue)) => Err(Self::json_err(
51 "key not allowed: previous key has no value yet",
52 )),
53 Some(Frame::Array) => Err(Self::json_err("key not allowed: inside an array")),
54 Some(Frame::Root) => Err(Self::json_err("key not allowed: not inside an object")),
55 None => Err(Self::json_err("key not allowed: no current frame")),
56 }
57 }
58
59 #[inline]
65 pub fn expect_value_allowed(&self) -> Result<()> {
66 match self.stack.last() {
67 Some(Frame::Object(KeyState::ExpectingValue) | Frame::Array | Frame::Root) => Ok(()),
68 Some(Frame::Object(KeyState::ExpectingKey)) => Err(Self::json_err(
69 "value not allowed: object expects a key first",
70 )),
71 None => Err(Self::json_err("value not allowed: no current frame")),
72 }
73 }
74
75 #[inline]
77 #[must_use]
78 pub fn is_finished(&self) -> bool {
79 self.stack.is_empty()
80 }
81
82 #[inline]
87 fn json_err(msg: &str) -> Error {
88 Error::Json {
89 message: msg.to_string(),
90 position: None,
91 }
92 }
93
94 #[inline]
100 pub fn mark_key_written(&mut self) -> Result<()> {
101 match self.stack.last_mut() {
102 Some(Frame::Object(ks)) if *ks == KeyState::ExpectingKey => {
103 *ks = KeyState::ExpectingValue;
104 Ok(())
105 }
106 Some(Frame::Object(_)) => {
107 Err(Self::json_err("key already written; expected a value next"))
108 }
109 _ => Err(Self::json_err("cannot write key: not inside an object")),
110 }
111 }
112
113 #[inline]
121 pub fn mark_value_written(&mut self) -> Result<()> {
122 match self.stack.last_mut() {
123 Some(Frame::Object(ks)) if *ks == KeyState::ExpectingValue => {
124 *ks = KeyState::ExpectingKey;
125 Ok(())
126 }
127 Some(Frame::Object(_)) => {
128 Err(Self::json_err("value without key: object expects a key"))
129 }
130 Some(Frame::Array) => Ok(()),
131 Some(Frame::Root) => {
132 self.stack.pop();
133 Ok(())
134 }
135 None => Err(Self::json_err("no current frame for value")),
136 }
137 }
138
139 #[inline]
141 #[must_use]
142 pub fn new() -> Self {
143 Self {
144 stack: vec![Frame::Root],
145 }
146 }
147
148 #[inline]
154 pub fn peek_array(&self) -> Result<()> {
155 match self.stack.last() {
156 Some(Frame::Array) => Ok(()),
157 Some(Frame::Object(_)) => Err(Self::json_err(
158 "cannot close array: current frame is an object",
159 )),
160 _ => Err(Self::json_err("cannot close array: no open array")),
161 }
162 }
163
164 #[inline]
171 pub fn peek_object(&self) -> Result<()> {
172 match self.stack.last() {
173 Some(Frame::Object(KeyState::ExpectingKey)) => Ok(()),
174 Some(Frame::Object(KeyState::ExpectingValue)) => {
175 Err(Self::json_err("cannot close object: last key has no value"))
176 }
177 Some(Frame::Array) => Err(Self::json_err(
178 "cannot close object: current frame is an array",
179 )),
180 _ => Err(Self::json_err("cannot close object: no open object")),
181 }
182 }
183
184 #[inline]
190 pub fn pop(&mut self) -> Result<Frame> {
191 self.stack
192 .pop()
193 .ok_or_else(|| Self::json_err("cannot close: no open container"))
194 }
195
196 #[inline]
202 pub fn pop_array(&mut self) -> Result<()> {
203 self.peek_array()?;
204 let _ = self.stack.pop();
205 Ok(())
206 }
207
208 #[inline]
214 pub fn pop_object(&mut self) -> Result<()> {
215 self.peek_object()?;
216 let _ = self.stack.pop();
217 Ok(())
218 }
219
220 #[inline]
222 pub fn push_array(&mut self) {
223 self.stack.push(Frame::Array);
224 }
225
226 #[inline]
228 pub fn push_object(&mut self) {
229 self.stack.push(Frame::Object(KeyState::ExpectingKey));
230 }
231}
232
233impl Default for StateStack {
234 #[inline]
235 fn default() -> Self {
236 Self::new()
237 }
238}
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243
244 #[test]
245 fn new_returns_root_frame() {
246 let s = StateStack::new();
247 assert_eq!(s.current(), Some(&Frame::Root));
248 }
249
250 #[test]
251 fn push_pop_object_round_trip() {
252 let mut s = StateStack::new();
253 s.push_object();
254 assert!(matches!(
255 s.current(),
256 Some(Frame::Object(KeyState::ExpectingKey))
257 ));
258 assert!(s.pop_object().is_ok());
259 }
260
261 #[test]
262 fn push_pop_array_round_trip() {
263 let mut s = StateStack::new();
264 s.push_array();
265 assert_eq!(s.current(), Some(&Frame::Array));
266 assert!(s.pop_array().is_ok());
267 }
268
269 #[test]
270 fn nested_push_pop_lifo_order() {
271 let mut s = StateStack::new();
272 s.push_object();
273 s.push_array();
274 assert_eq!(s.current(), Some(&Frame::Array));
275 assert!(s.pop_array().is_ok());
276 assert!(matches!(s.current(), Some(Frame::Object(_))));
277 }
278
279 #[test]
280 fn pop_at_root_returns_error() {
281 let mut s = StateStack::new();
282 s.stack.clear();
283 assert!(s.pop().is_err());
284 }
285
286 #[test]
287 fn peek_array_at_root_errors() {
288 let s = StateStack::new();
289 assert!(s.peek_array().is_err());
290 }
291
292 #[test]
293 fn peek_array_when_top_is_array_succeeds() {
294 let mut s = StateStack::new();
295 s.push_array();
296 assert!(s.peek_array().is_ok());
297 assert_eq!(s.current(), Some(&Frame::Array));
298 }
299
300 #[test]
301 fn peek_array_when_top_is_object_errors() {
302 let mut s = StateStack::new();
303 s.push_object();
304 assert!(s.peek_array().is_err());
305 }
306
307 #[test]
308 fn peek_object_at_root_errors() {
309 let s = StateStack::new();
310 assert!(s.peek_object().is_err());
311 }
312
313 #[test]
314 fn peek_object_when_top_is_array_errors() {
315 let mut s = StateStack::new();
316 s.push_array();
317 assert!(s.peek_object().is_err());
318 }
319
320 #[test]
321 fn peek_object_when_top_is_object_expecting_key_succeeds() {
322 let mut s = StateStack::new();
323 s.push_object();
324 assert!(s.peek_object().is_ok());
325 }
326
327 #[test]
328 fn peek_object_when_top_is_object_expecting_value_errors() {
329 let mut s = StateStack::new();
330 s.push_object();
331 assert!(s.mark_key_written().is_ok());
332 assert!(s.peek_object().is_err());
333 }
334
335 #[test]
336 fn pop_object_when_top_is_object_succeeds() {
337 let mut s = StateStack::new();
338 s.push_object();
339 assert!(s.pop_object().is_ok());
340 }
341
342 #[test]
343 fn pop_object_when_top_is_array_errors() {
344 let mut s = StateStack::new();
345 s.push_array();
346 assert!(s.pop_object().is_err());
347 }
348
349 #[test]
350 fn pop_object_at_root_errors() {
351 let mut s = StateStack::new();
352 assert!(s.pop_object().is_err());
353 }
354
355 #[test]
356 fn pop_object_in_expecting_value_errors() {
357 let mut s = StateStack::new();
358 s.push_object();
359 assert!(s.mark_key_written().is_ok());
360 assert!(s.pop_object().is_err());
361 }
362
363 #[test]
364 fn pop_array_when_top_is_array_succeeds() {
365 let mut s = StateStack::new();
366 s.push_array();
367 assert!(s.pop_array().is_ok());
368 }
369
370 #[test]
371 fn pop_array_when_top_is_object_errors() {
372 let mut s = StateStack::new();
373 s.push_object();
374 assert!(s.pop_array().is_err());
375 }
376
377 #[test]
378 fn pop_array_at_root_errors() {
379 let mut s = StateStack::new();
380 assert!(s.pop_array().is_err());
381 }
382
383 #[test]
384 fn mark_key_written_in_object_expecting_key_transitions_to_expecting_value() {
385 let mut s = StateStack::new();
386 s.push_object();
387 assert!(s.mark_key_written().is_ok());
388 assert!(matches!(
389 s.current(),
390 Some(Frame::Object(KeyState::ExpectingValue))
391 ));
392 }
393
394 #[test]
395 fn mark_key_written_in_object_expecting_value_errors() {
396 let mut s = StateStack::new();
397 s.push_object();
398 assert!(s.mark_key_written().is_ok());
399 assert!(s.mark_key_written().is_err());
400 }
401
402 #[test]
403 fn mark_key_written_in_array_errors() {
404 let mut s = StateStack::new();
405 s.push_array();
406 assert!(s.mark_key_written().is_err());
407 }
408
409 #[test]
410 fn mark_key_written_at_root_errors() {
411 let mut s = StateStack::new();
412 assert!(s.mark_key_written().is_err());
413 }
414
415 #[test]
416 fn mark_value_written_in_object_expecting_value_transitions_back() {
417 let mut s = StateStack::new();
418 s.push_object();
419 assert!(s.mark_key_written().is_ok());
420 assert!(s.mark_value_written().is_ok());
421 assert!(matches!(
422 s.current(),
423 Some(Frame::Object(KeyState::ExpectingKey))
424 ));
425 }
426
427 #[test]
428 fn mark_value_written_in_object_expecting_key_errors() {
429 let mut s = StateStack::new();
430 s.push_object();
431 assert!(s.mark_value_written().is_err());
432 }
433
434 #[test]
435 fn mark_value_written_without_frame_errors() {
436 let mut s = StateStack::new();
437 s.stack.clear();
438 assert!(s.mark_value_written().is_err());
439 }
440
441 #[test]
442 fn mark_value_written_in_array_no_transition() {
443 let mut s = StateStack::new();
444 s.push_array();
445 assert!(s.mark_value_written().is_ok());
446 assert_eq!(s.current(), Some(&Frame::Array));
447 }
448
449 #[test]
450 fn mark_value_written_at_root_consumes_root() {
451 let mut s = StateStack::new();
452 assert!(s.mark_value_written().is_ok());
453 assert!(s.is_finished());
454 }
455
456 #[test]
457 fn expect_key_allowed_only_in_object_expecting_key() {
458 let mut s = StateStack::new();
459 assert!(s.expect_key_allowed().is_err());
460 s.push_array();
461 assert!(s.expect_key_allowed().is_err());
462 assert!(s.pop_array().is_ok());
463 s.push_object();
464 assert!(s.expect_key_allowed().is_ok());
465 assert!(s.mark_key_written().is_ok());
466 assert!(s.expect_key_allowed().is_err());
467 }
468
469 #[test]
470 fn expect_key_allowed_without_frame_errors() {
471 let mut s = StateStack::new();
472 s.stack.clear();
473 assert!(s.expect_key_allowed().is_err());
474 }
475
476 #[test]
477 fn expect_value_allowed_in_root_object_value_and_array_only() {
478 let mut s = StateStack::new();
479 assert!(s.expect_value_allowed().is_ok());
480 s.push_object();
481 assert!(s.expect_value_allowed().is_err());
482 assert!(s.mark_key_written().is_ok());
483 assert!(s.expect_value_allowed().is_ok());
484 assert!(s.mark_value_written().is_ok());
485 s.push_array();
486 assert!(s.expect_value_allowed().is_ok());
487 }
488
489 #[test]
490 fn expect_value_allowed_without_frame_errors() {
491 let mut s = StateStack::new();
492 s.stack.clear();
493 assert!(s.expect_value_allowed().is_err());
494 }
495
496 #[test]
497 fn is_finished_true_after_root_value_consumed() {
498 let mut s = StateStack::new();
499 assert!(s.mark_value_written().is_ok());
500 assert!(s.is_finished());
501 }
502
503 #[test]
504 fn is_finished_false_inside_open_container() {
505 let mut s = StateStack::new();
506 s.push_object();
507 assert!(!s.is_finished());
508 }
509
510 #[test]
511 fn state_stack_default_returns_root_frame() {
512 let s = StateStack::default();
513 assert_eq!(s.current(), Some(&Frame::Root));
514 }
515}