json_syntax/
kind.rs

1//! JSON value kinds.
2use core::fmt;
3
4/// Value kind.
5#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
6pub enum Kind {
7	Null,
8	Boolean,
9	Number,
10	String,
11	Array,
12	Object,
13}
14
15impl std::ops::BitOr for Kind {
16	type Output = KindSet;
17
18	fn bitor(self, other: Self) -> KindSet {
19		KindSet::from(self) | KindSet::from(other)
20	}
21}
22
23impl std::ops::BitOr<KindSet> for Kind {
24	type Output = KindSet;
25
26	fn bitor(self, other: KindSet) -> KindSet {
27		KindSet::from(self) | other
28	}
29}
30
31impl std::ops::BitAnd for Kind {
32	type Output = KindSet;
33
34	fn bitand(self, other: Self) -> KindSet {
35		KindSet::from(self) & KindSet::from(other)
36	}
37}
38
39impl std::ops::BitAnd<KindSet> for Kind {
40	type Output = KindSet;
41
42	fn bitand(self, other: KindSet) -> KindSet {
43		KindSet::from(self) & other
44	}
45}
46
47impl fmt::Display for Kind {
48	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49		match self {
50			Self::Null => write!(f, "null"),
51			Self::Boolean => write!(f, "boolean"),
52			Self::Number => write!(f, "number"),
53			Self::String => write!(f, "string"),
54			Self::Array => write!(f, "array"),
55			Self::Object => write!(f, "object"),
56		}
57	}
58}
59
60macro_rules! kind_set {
61	($($id:ident ($const:ident): $mask:literal),*) => {
62		/// Set of JSON value [`Kind`].
63		#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
64		pub struct KindSet(u8);
65
66		impl KindSet {
67			$(
68				pub const $const: Self = Self($mask);
69			)*
70
71			pub const fn all() -> Self {
72				Self($($mask)|*)
73			}
74		}
75
76		impl std::ops::BitOr<Kind> for KindSet {
77			type Output = Self;
78
79			fn bitor(self, other: Kind) -> Self {
80				match other {
81					$(
82						Kind::$id => Self(self.0 | $mask)
83					),*
84				}
85			}
86		}
87
88		impl std::ops::BitOrAssign<Kind> for KindSet {
89			fn bitor_assign(&mut self, other: Kind) {
90				match other {
91					$(
92						Kind::$id => self.0 |= $mask
93					),*
94				}
95			}
96		}
97
98		impl std::ops::BitAnd<Kind> for KindSet {
99			type Output = Self;
100
101			fn bitand(self, other: Kind) -> Self {
102				match other {
103					$(
104						Kind::$id => Self(self.0 & $mask)
105					),*
106				}
107			}
108		}
109
110		impl std::ops::BitAndAssign<Kind> for KindSet {
111			fn bitand_assign(&mut self, other: Kind) {
112				match other {
113					$(
114						Kind::$id => self.0 &= $mask
115					),*
116				}
117			}
118		}
119
120		impl From<Kind> for KindSet {
121			fn from(value: Kind) -> Self {
122				match value {
123					$(
124						Kind::$id => Self($mask)
125					),*
126				}
127			}
128		}
129
130		#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
131		pub struct KindSetIter(u8);
132
133		impl Iterator for KindSetIter {
134			type Item = Kind;
135
136			fn size_hint(&self) -> (usize, Option<usize>) {
137				let len = self.0.count_ones() as usize;
138				(len, Some(len))
139			}
140
141			fn next(&mut self) -> Option<Kind> {
142				$(
143					if self.0 & $mask != 0 {
144						self.0 &= !$mask;
145						return Some(Kind::$id)
146					}
147				)*
148
149				None
150			}
151		}
152
153		impl DoubleEndedIterator for KindSetIter {
154			fn next_back(&mut self) -> Option<Kind> {
155				let mut result = None;
156
157				$(
158					if self.0 & $mask != 0 {
159						result = Some((Kind::$id, $mask));
160					}
161				)*
162
163				result.map(|(kind, mask)| {
164					self.0 &= !mask;
165					kind
166				})
167			}
168		}
169
170		impl std::iter::FusedIterator for KindSetIter {}
171		impl std::iter::ExactSizeIterator for KindSetIter {}
172	};
173}
174
175kind_set! {
176	Null (NULL):       0b000001,
177	Boolean (BOOLEAN): 0b000010,
178	Number (NUMBER):   0b000100,
179	String (STRING):   0b001000,
180	Array (ARRAY):     0b010000,
181	Object (OBJECT):   0b100000
182}
183
184impl KindSet {
185	pub const fn none() -> Self {
186		Self(0)
187	}
188
189	pub const fn len(&self) -> usize {
190		self.0.count_ones() as usize
191	}
192
193	pub const fn is_empty(&self) -> bool {
194		self.0 == 0
195	}
196
197	pub fn iter(&self) -> KindSetIter {
198		KindSetIter(self.0)
199	}
200
201	/// Displays this set as a disjunction.
202	///
203	/// # Example
204	///
205	/// ```
206	/// # use json_syntax::{Kind, KindSet};
207	/// let set = Kind::Null | Kind::String | Kind::Object;
208	/// assert_eq!(set.as_disjunction().to_string(), "null, string or object");
209	/// assert_eq!(KindSet::ARRAY.as_disjunction().to_string(), "array");
210	/// assert_eq!(KindSet::all().as_disjunction().to_string(), "anything");
211	/// assert_eq!(KindSet::none().as_disjunction().to_string(), "nothing");
212	/// ```
213	pub fn as_disjunction(self) -> KindSetDisjunction {
214		KindSetDisjunction(self)
215	}
216
217	/// Displays this set as a conjunction.
218	///
219	/// # Example
220	///
221	/// ```
222	/// # use json_syntax::{Kind, KindSet};
223	/// let set = Kind::Null | Kind::String | Kind::Object;
224	/// assert_eq!(set.as_conjunction().to_string(), "null, string and object");
225	/// assert_eq!(KindSet::ARRAY.as_conjunction().to_string(), "array");
226	/// assert_eq!(KindSet::all().as_conjunction().to_string(), "anything");
227	/// assert_eq!(KindSet::none().as_conjunction().to_string(), "nothing");
228	/// ```
229	pub fn as_conjunction(self) -> KindSetConjunction {
230		KindSetConjunction(self)
231	}
232}
233
234impl std::ops::BitOr for KindSet {
235	type Output = Self;
236
237	fn bitor(self, other: Self) -> Self {
238		Self(self.0 | other.0)
239	}
240}
241
242impl std::ops::BitOrAssign for KindSet {
243	fn bitor_assign(&mut self, other: Self) {
244		self.0 |= other.0
245	}
246}
247
248impl std::ops::BitAnd for KindSet {
249	type Output = Self;
250
251	fn bitand(self, other: Self) -> Self {
252		Self(self.0 & other.0)
253	}
254}
255
256impl std::ops::BitAndAssign for KindSet {
257	fn bitand_assign(&mut self, other: Self) {
258		self.0 &= other.0
259	}
260}
261
262impl<'a> IntoIterator for &'a KindSet {
263	type IntoIter = KindSetIter;
264	type Item = Kind;
265
266	fn into_iter(self) -> KindSetIter {
267		self.iter()
268	}
269}
270
271impl IntoIterator for KindSet {
272	type IntoIter = KindSetIter;
273	type Item = Kind;
274
275	fn into_iter(self) -> KindSetIter {
276		self.iter()
277	}
278}
279
280impl fmt::Display for KindSet {
281	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282		for (i, kind) in self.into_iter().enumerate() {
283			if i > 0 {
284				f.write_str(", ")?;
285			}
286
287			kind.fmt(f)?;
288		}
289
290		Ok(())
291	}
292}
293
294/// Displays a `KindSet` as a disjunction.
295#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
296pub struct KindSetDisjunction(pub KindSet);
297
298impl fmt::Display for KindSetDisjunction {
299	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300		if self.0 == KindSet::all() {
301			f.write_str("anything")
302		} else {
303			let mut iter = self.0.into_iter();
304			match iter.next_back() {
305				Some(last) => {
306					if let Some(first) = iter.next() {
307						first.fmt(f)?;
308						for k in iter {
309							f.write_str(", ")?;
310							k.fmt(f)?;
311						}
312						f.write_str(" or ")?;
313					}
314
315					last.fmt(f)
316				}
317				None => f.write_str("nothing"),
318			}
319		}
320	}
321}
322
323/// Displays a `KindSet` as a conjunction.
324#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
325pub struct KindSetConjunction(pub KindSet);
326
327impl fmt::Display for KindSetConjunction {
328	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
329		if self.0 == KindSet::all() {
330			f.write_str("anything")
331		} else {
332			let mut iter = self.0.into_iter();
333			match iter.next_back() {
334				Some(last) => {
335					if let Some(first) = iter.next() {
336						first.fmt(f)?;
337						for k in iter {
338							f.write_str(", ")?;
339							k.fmt(f)?;
340						}
341						f.write_str(" and ")?;
342					}
343
344					last.fmt(f)
345				}
346				None => f.write_str("nothing"),
347			}
348		}
349	}
350}