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