Skip to main content

just_kdl/
validator.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2//! Verification of event streams.
3//!
4//! Most library functions produce and expect to receive structurally-valid
5//! event streams, use this to ensure untrusted event streams are valid.
6//!
7//! You probably want to start at [`Validator`].
8
9use std::error::Error;
10
11use displaydoc::Display;
12
13use crate::dom::Event;
14
15/// Error in validation
16#[derive(Clone, Debug, Display)]
17#[non_exhaustive]
18pub enum ValidatorError {
19	/// Too many End events
20	TooManyEnd,
21	/// Unclosed nodes at end
22	Unclosed,
23	/// Expected {0}, got {1:?}
24	Expected(&'static str, Event),
25}
26impl Error for ValidatorError {}
27
28#[derive(Debug, Clone, Copy)]
29enum State {
30	/// Node, End, Done
31	Block,
32	/// Entry, Children, End
33	Node,
34}
35
36/// Event stream validator
37#[derive(Debug)]
38pub struct Validator {
39	nest: usize,
40	state: State,
41}
42
43impl Default for Validator {
44	fn default() -> Self { Self::new() }
45}
46
47impl Validator {
48	/// Create a new validator.
49	pub const fn new() -> Self {
50		Self {
51			nest: 0,
52			state: State::Block,
53		}
54	}
55	/// Feed an event into validator.
56	/// # Errors
57	/// Returns any validation errors.
58	pub fn push(&mut self, event: &Event) -> Result<(), ValidatorError> {
59		self.state = match (self.state, event) {
60			(_, Event::End) => {
61				if let Some(nest) = self.nest.checked_sub(1) {
62					self.nest = nest;
63					State::Block
64				} else {
65					return Err(ValidatorError::TooManyEnd);
66				}
67			}
68			(State::Node, Event::Entry { .. }) => State::Node,
69			(State::Node, Event::Children) => State::Block,
70			(State::Block, Event::Node { .. }) => {
71				self.nest += 1;
72				State::Node
73			}
74			(State::Node, event) => {
75				return Err(ValidatorError::Expected(
76					"Entry, Children, or End",
77					event.clone(),
78				));
79			}
80			(State::Block, event) => {
81				return Err(ValidatorError::Expected("Node or End", event.clone()));
82			}
83		};
84		Ok(())
85	}
86	/// Mark the end of the event stream.
87	/// # Errors
88	/// Returns a validation error from any unclosed nodes
89	pub fn done(self) -> Result<(), ValidatorError> {
90		if self.nest > 0 {
91			Err(ValidatorError::Unclosed)
92		} else {
93			Ok(())
94		}
95	}
96}