1use core::fmt;
3use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
4
5#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
16pub enum Kind {
17 Null,
19
20 Boolean,
22
23 Number,
25
26 String,
28
29 Array,
31
32 Object,
34}
35
36impl BitOr for Kind {
37 type Output = KindSet;
38
39 fn bitor(self, other: Self) -> KindSet {
40 KindSet::from(self) | KindSet::from(other)
41 }
42}
43
44impl BitOr<KindSet> for Kind {
45 type Output = KindSet;
46
47 fn bitor(self, other: KindSet) -> KindSet {
48 KindSet::from(self) | other
49 }
50}
51
52impl BitAnd for Kind {
53 type Output = KindSet;
54
55 fn bitand(self, other: Self) -> KindSet {
56 KindSet::from(self) & KindSet::from(other)
57 }
58}
59
60impl BitAnd<KindSet> for Kind {
61 type Output = KindSet;
62
63 fn bitand(self, other: KindSet) -> KindSet {
64 KindSet::from(self) & other
65 }
66}
67
68impl fmt::Display for Kind {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 match self {
71 Self::Null => write!(f, "null"),
72 Self::Boolean => write!(f, "boolean"),
73 Self::Number => write!(f, "number"),
74 Self::String => write!(f, "string"),
75 Self::Array => write!(f, "array"),
76 Self::Object => write!(f, "object"),
77 }
78 }
79}
80
81macro_rules! kind_set {
82 ($($id:ident ($const:ident): $mask:literal),*) => {
83 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
85 pub struct KindSet(u8);
86
87 impl KindSet {
88 $(
89 #[doc = concat!("Set containing only [`Kind::", stringify!($id), "`].")]
90 pub const $const: Self = Self($mask);
91 )*
92
93 pub const fn all() -> Self {
95 Self($($mask)|*)
96 }
97 }
98
99 impl std::ops::BitOr<Kind> for KindSet {
100 type Output = Self;
101
102 fn bitor(self, other: Kind) -> Self {
103 match other {
104 $(
105 Kind::$id => Self(self.0 | $mask)
106 ),*
107 }
108 }
109 }
110
111 impl std::ops::BitOrAssign<Kind> for KindSet {
112 fn bitor_assign(&mut self, other: Kind) {
113 match other {
114 $(
115 Kind::$id => self.0 |= $mask
116 ),*
117 }
118 }
119 }
120
121 impl std::ops::BitAnd<Kind> for KindSet {
122 type Output = Self;
123
124 fn bitand(self, other: Kind) -> Self {
125 match other {
126 $(
127 Kind::$id => Self(self.0 & $mask)
128 ),*
129 }
130 }
131 }
132
133 impl std::ops::BitAndAssign<Kind> for KindSet {
134 fn bitand_assign(&mut self, other: Kind) {
135 match other {
136 $(
137 Kind::$id => self.0 &= $mask
138 ),*
139 }
140 }
141 }
142
143 impl From<Kind> for KindSet {
144 fn from(value: Kind) -> Self {
145 match value {
146 $(
147 Kind::$id => Self($mask)
148 ),*
149 }
150 }
151 }
152
153 #[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
155 pub struct KindSetIter(u8);
156
157 impl Iterator for KindSetIter {
158 type Item = Kind;
159
160 fn size_hint(&self) -> (usize, Option<usize>) {
161 let len = self.0.count_ones() as usize;
162 (len, Some(len))
163 }
164
165 fn next(&mut self) -> Option<Kind> {
166 $(
167 if self.0 & $mask != 0 {
168 self.0 &= !$mask;
169 return Some(Kind::$id)
170 }
171 )*
172
173 None
174 }
175 }
176
177 impl DoubleEndedIterator for KindSetIter {
178 fn next_back(&mut self) -> Option<Kind> {
179 let mut result = None;
180
181 $(
182 if self.0 & $mask != 0 {
183 result = Some((Kind::$id, $mask));
184 }
185 )*
186
187 result.map(|(kind, mask)| {
188 self.0 &= !mask;
189 kind
190 })
191 }
192 }
193
194 impl core::iter::FusedIterator for KindSetIter {}
195 impl core::iter::ExactSizeIterator for KindSetIter {}
196 };
197}
198
199kind_set! {
200 Null (NULL): 0b00_0001,
201 Boolean (BOOLEAN): 0b00_0010,
202 Number (NUMBER): 0b00_0100,
203 String (STRING): 0b00_1000,
204 Array (ARRAY): 0b01_0000,
205 Object (OBJECT): 0b10_0000
206}
207
208impl KindSet {
209 #[must_use]
211 pub const fn none() -> Self {
212 Self(0)
213 }
214
215 #[must_use]
217 pub const fn len(&self) -> usize {
218 self.0.count_ones() as usize
219 }
220
221 #[must_use]
223 pub const fn is_empty(&self) -> bool {
224 self.0 == 0
225 }
226
227 #[must_use]
229 pub const fn iter(&self) -> KindSetIter {
230 KindSetIter(self.0)
231 }
232
233 #[must_use]
246 pub const fn as_disjunction(self) -> KindSetDisjunction {
247 KindSetDisjunction(self)
248 }
249
250 #[must_use]
263 pub const fn as_conjunction(self) -> KindSetConjunction {
264 KindSetConjunction(self)
265 }
266}
267
268impl BitOr for KindSet {
269 type Output = Self;
270
271 fn bitor(self, other: Self) -> Self {
272 Self(self.0 | other.0)
273 }
274}
275
276impl BitOrAssign for KindSet {
277 fn bitor_assign(&mut self, other: Self) {
278 self.0 |= other.0;
279 }
280}
281
282impl BitAnd for KindSet {
283 type Output = Self;
284
285 fn bitand(self, other: Self) -> Self {
286 Self(self.0 & other.0)
287 }
288}
289
290impl BitAndAssign for KindSet {
291 fn bitand_assign(&mut self, other: Self) {
292 self.0 &= other.0;
293 }
294}
295
296impl IntoIterator for &KindSet {
297 type IntoIter = KindSetIter;
298 type Item = Kind;
299
300 fn into_iter(self) -> KindSetIter {
301 self.iter()
302 }
303}
304
305impl IntoIterator for KindSet {
306 type IntoIter = KindSetIter;
307 type Item = Kind;
308
309 fn into_iter(self) -> KindSetIter {
310 self.iter()
311 }
312}
313
314impl fmt::Display for KindSet {
315 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316 for (i, kind) in self.into_iter().enumerate() {
317 if i > 0 {
318 f.write_str(", ")?;
319 }
320
321 kind.fmt(f)?;
322 }
323
324 Ok(())
325 }
326}
327
328#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
330pub struct KindSetDisjunction(pub KindSet);
331
332impl fmt::Display for KindSetDisjunction {
333 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334 if self.0 == KindSet::all() {
335 f.write_str("anything")
336 } else {
337 let mut iter = self.0.into_iter();
338 match iter.next_back() {
339 Some(last) => {
340 if let Some(first) = iter.next() {
341 first.fmt(f)?;
342 for k in iter {
343 f.write_str(", ")?;
344 k.fmt(f)?;
345 }
346 f.write_str(" or ")?;
347 }
348
349 last.fmt(f)
350 }
351 None => f.write_str("nothing"),
352 }
353 }
354 }
355}
356
357#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
359pub struct KindSetConjunction(pub KindSet);
360
361impl fmt::Display for KindSetConjunction {
362 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
363 if self.0 == KindSet::all() {
364 f.write_str("anything")
365 } else {
366 let mut iter = self.0.into_iter();
367 match iter.next_back() {
368 Some(last) => {
369 if let Some(first) = iter.next() {
370 first.fmt(f)?;
371 for k in iter {
372 f.write_str(", ")?;
373 k.fmt(f)?;
374 }
375 f.write_str(" and ")?;
376 }
377
378 last.fmt(f)
379 }
380 None => f.write_str("nothing"),
381 }
382 }
383 }
384}