1pub mod parser;
11pub mod token;
12
13#[derive(thiserror::Error, Debug)]
15pub enum Error {
16	#[error("Error: {0}")]
18	Error(String),
19
20	#[error("Invalid String: {0}")]
22	InvalidString(String),
23
24	#[error("Tokenize: {0}")]
26	Tokenize(String),
27
28	#[error("Unexpected token")]
29	UnexpectedToken,
30
31	#[error("Unexpected length")]
32	UnexpectedLength,
33
34	#[error("Unexpected value")]
35	UnexpectedValue,
36
37	#[error("Unsupported")]
38	Unsupported,
39
40	#[error("Parse: {0}")]
42	Parser(String),
43
44	#[error("serde_json")]
45	Serde(#[from] serde_json::Error),
46
47	#[error("IO")]
48	Io(#[from] std::io::Error),
49
50	#[error("Utf8")]
51	Utf8(#[from] std::str::Utf8Error),
52}
53type Result<T> = std::result::Result<T, Error>;
54
55macro_rules! errloc {
56	() => {{
57		let line = line!();
58		let file = file!();
59		format!("{file}:{line}")
60	}};
61}
62
63pub(crate) use errloc;
64
65macro_rules! parsererror {
66	($msg:expr) => {{
67		let errloc = crate::errloc!();
68		let err = format!("{errloc}: error: {}", $msg);
69		log::error!("{err}");
70		Err(crate::Error::Parser(err))
71	}};
72}
73pub(crate) use parsererror;
74
75macro_rules! generror {
76	($msg:expr, $log:ident) => {{
77		let errloc = crate::errloc!();
78		let err = format!("{errloc}: error: {}", $msg);
79		log::$log!("{err}");
80		Err(crate::Error::Error(err))
81	}};
82	($msg:expr) => {
83		generror!($msg, error)
84	};
85}
86pub(crate) use generror;
87
88macro_rules! verify {
89	($expr:expr, $error:ident) => {
90		if (!($expr)) {
91			let errloc = crate::errloc!();
92			log::error!("{errloc}: expression failed: {}", stringify!($expr));
93			return Err(crate::Error::$error);
94		}
95	};
96}
97pub(crate) use verify;
98
99macro_rules! consume {
100	($tokens:expr, $check:expr) => {{
101		if $tokens.is_empty() {
102			let errloc = crate::errloc!();
103			let msg = format!("{errloc}: expected {:?}, but tokens is empty", $check);
104			log::error!("{msg}");
105			return Err(crate::Error::Parser(msg));
106		}
107		let t = $tokens.remove(0);
108		if t != $check {
109			let errloc = crate::errloc!();
110			let msg = format!("{errloc}: expected {:?}, but got token {:?}", $check, t);
111			log::error!("{msg}");
112			return Err(crate::Error::Parser(msg));
113		}
114		t
115	}};
116	($tokens:expr) => {{
117		if $tokens.is_empty() {
118			let errloc = crate::errloc!();
119			let msg = format!("{errloc}: expected new value but tokens is empty");
120			log::error!("{msg}");
121			return Err(crate::Error::Parser(msg));
122		}
123		$tokens.remove(0)
124	}};
125}
126pub(crate) use consume;
127
128macro_rules! check_empty {
129	($tokens:expr) => {
130		if !$tokens.is_empty() {
131			let errloc = crate::errloc!();
132			let msg = format!("{errloc}: expected tokens to be empty, left: {:?}", $tokens);
133			log::error!("{msg}");
134			return Err(crate::Error::Parser(msg));
135		}
136	};
137}
138pub(crate) use check_empty;
139
140macro_rules! gen_get_ident {
141	($name:ident) => {
142		pub fn identifier(&self) -> &Identifier {
144			&self.$name
145		}
146	};
147}
148pub(crate) use gen_get_ident;
149
150macro_rules! gen_get {
151	($funcname:ident, $field:ident, $val:ty) => {
152		pub fn $funcname(&self) -> &$val {
153			&self.$field
154		}
155	};
156	($field:ident, $val:ty) => {
157		gen_get! { $field, $field, $val }
158	};
159}
160
161pub(crate) use gen_get;
162
163macro_rules! gen_get_mut {
164	($funcname:ident, $field:ident, $val:ty) => {
165		pub fn $funcname(&mut self) -> &mut $val {
166			&mut self.$field
167		}
168	};
169	($field:ident, $val:ty) => {
170		gen_get_mut! { $field, $field, $val }
171	};
172}
173
174pub(crate) use gen_get_mut;
175
176macro_rules! gen_get_iter {
177	($funcname:ident, $field:ident, $val:ty) => {
178		pub fn $funcname(&self) -> std::slice::Iter<'_, $val> {
179			self.$field.iter()
180		}
181	};
182	($field:ident, $val:ty) => {
183		gen_get_iter! { $field, $field, $val }
184	};
185}
186pub(crate) use gen_get_iter;
187
188macro_rules! gen_find_ident {
189	($field:ident) => {
190		pub fn find_ident<'a>(entries: &'a [Self], ident: &Identifier) -> Option<&'a Self> {
192			for val in entries.iter() {
193				if val.$field == *ident {
194					return Some(val);
195				}
196			}
197			None
198		}
199	};
200	($field:ident, $val:ty) => {
201		gen_get_iter! { $field, $field, $val }
202	};
203}
204pub(crate) use gen_find_ident;
205
206macro_rules! gen_get_ident_matches {
207	($name:ident) => {
208		pub fn ident_matches(&self, name: &str) -> bool {
210			self.$name.name == name
211		}
212	};
213}
214pub(crate) use gen_get_ident_matches;
215
216macro_rules! gen_find_by_ident {
217	($name:ident, $field:ident, $val:ty) => {
218		pub fn $name(&self, ident: &Identifier) -> Option<&$val> {
219			self.$field.iter().find(|&s| s.identifier() == ident)
220		}
221	};
222}
223pub(crate) use gen_find_by_ident;
224
225macro_rules! gen_find_by_name {
226	($name:ident, $field:ident, $val:ty) => {
227		pub fn $name<I: Into<Identifier>>(&self, name: I) -> Option<&$val> {
228			let ident: Identifier = name.into();
229			self.$field.iter().find(|&s| s.identifier() == &ident)
230		}
231	};
232}
233pub(crate) use gen_find_by_name;
234
235#[cfg(test)]
236#[ctor::ctor]
237fn global_test_setup() {
238	env_logger::init();
239}