1use core::marker::PhantomData;
2use std::collections::BTreeMap;
3
4#[cfg(feature = "serde")]
5use serde::Serialize;
6
7pub trait FiniteSet<const N: usize>: Copy + Sized {
9 const ALL: [Self; N];
10 const LEN: usize = N;
11
12 #[inline]
13 fn iter() -> impl Iterator<Item = Self> {
14 Self::ALL.into_iter()
15 }
16
17 #[inline]
18 fn iter_rev() -> impl Iterator<Item = Self> {
19 Self::ALL.into_iter().rev()
20 }
21}
22
23pub trait Empty {
24 const EMPTY: Self;
25
26 fn is_empty(&self) -> bool;
27}
28
29impl Empty for bool {
30 const EMPTY: Self = false;
31
32 fn is_empty(&self) -> bool {
33 !self
34 }
35}
36
37impl Empty for u8 {
38 const EMPTY: Self = 0;
39
40 fn is_empty(&self) -> bool {
41 *self == Self::EMPTY
42 }
43}
44
45impl Empty for u128 {
46 const EMPTY: Self = 0;
47
48 fn is_empty(&self) -> bool {
49 *self == Self::EMPTY
50 }
51}
52
53impl<T: Empty, const N: usize> Empty for [T; N] {
54 const EMPTY: Self = [const { T::EMPTY }; N];
55
56 fn is_empty(&self) -> bool {
57 self.iter().all(Empty::is_empty)
58 }
59}
60
61impl<T> Empty for Option<T> {
62 const EMPTY: Self = None;
63
64 fn is_empty(&self) -> bool {
65 self.is_none()
66 }
67}
68
69impl<T> Empty for Vec<T> {
70 const EMPTY: Self = Vec::new();
71
72 fn is_empty(&self) -> bool {
73 self.is_empty()
74 }
75}
76
77#[derive(Clone, Copy, Debug, Eq, PartialEq)]
79pub struct Table<X, T, const N: usize> {
80 pub all: [T; N],
81 __: PhantomData<X>,
82}
83
84impl<X, T, const N: usize> Table<X, T, N> {
85 #[inline]
86 pub const fn new(all: [T; N]) -> Self {
87 Self { all, __: PhantomData }
88 }
89}
90
91impl<X, T: Copy, const N: usize> Table<X, T, N> {
92 #[inline]
93 pub const fn filled(value: T) -> Self {
94 Self { all: [value; N], __: PhantomData }
95 }
96}
97
98impl<X, T: Empty, const N: usize> Empty for Table<X, T, N> {
99 const EMPTY: Self = Self::new([const { T::EMPTY }; N]);
100
101 fn is_empty(&self) -> bool {
102 self.all.iter().all(Empty::is_empty)
103 }
104}
105
106impl<X, T: Empty, const N: usize> Table<X, T, N> {
107 #[inline]
108 pub const fn empty() -> Self {
109 Self::EMPTY
110 }
111}
112
113impl<X, T: Default, const N: usize> Default for Table<X, T, N>
114where
115 [T; N]: Default,
116{
117 fn default() -> Self {
118 Self { all: Default::default(), __: PhantomData }
119 }
120}
121
122impl<X, T, const N: usize> From<Table<X, T, N>> for BTreeMap<X, T>
123where
124 T: Copy,
125 X: FiniteSet<N> + Ord,
126{
127 fn from(table: Table<X, T, N>) -> Self {
128 X::iter().zip(table.all).collect()
129 }
130}
131
132#[cfg(feature = "serde")]
133impl<X, T: Serialize, const N: usize> Serialize for Table<X, T, N>
134where
135 T: Copy + Serialize,
136 X: FiniteSet<N> + Ord + Serialize,
137{
138 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139 where
140 S: serde::Serializer,
141 {
142 Serialize::serialize(&BTreeMap::from(*self), serializer)
143 }
144}
145
146#[macro_export]
229macro_rules! finite_set {
230 (
231 $(#[$name_meta:meta])*
232 $name:ident,
233 $(#[$table_meta:meta])*
234 $table:ident {
235 $($(#[$variant_meta:meta])* $variant:ident $(= $value:tt)? as $field:tt),+ $(,)?
236 }
237 ) => {
238 $crate::finite_set! {
239 @table
240 { $crate::finite_set!(@count $($variant),+) },
241 { $(#[$name_meta])* },
242 $name,
243 { $(#[$table_meta])* },
244 $table,
245 $table {
246 $($(#[$variant_meta])* $variant $(= $value)? as $field),+
247 }
248 }
249 };
250
251 (
252 $(#[$name_meta:meta])*
253 $name:ident,
254 $(#[$table_meta:meta])*
255 $table:ident {
256 $($(#[$variant_meta:meta])* $variant:ident $(= $value:tt)? as $field:tt),+ $(,)?
257 },
258 $cursor:ident
259 ) => {
260 $crate::finite_set! {
261 @table
262 { $crate::finite_set!(@count $($variant),+) },
263 { $(#[$name_meta])* },
264 $name,
265 { $(#[$table_meta])* },
266 $table,
267 $table {
268 $($(#[$variant_meta])* $variant $(= $value)? as $field),+
269 }
270 }
271
272 $crate::finite_set! {
273 @cursor
274 { $crate::finite_set!(@count $($variant),+) },
275 $name,
276 $cursor
277 }
278 };
279
280 (
281 $(#[$name_meta:meta])*
282 $name:ident,
283 $(#[$record_meta:meta])*
284 $record:ident,
285 $(#[$table_meta:meta])*
286 $table:ident,
287 {
288 $($(#[$variant_meta:meta])* $variant:ident $(= $value:tt)? as $field:ident),+ $(,)?
289 }
290 ) => {
291 $crate::finite_set! {
292 @record
293 { $crate::finite_set!(@count $($variant),+) },
294 { $(#[$name_meta])* },
295 $name,
296 { $(#[$record_meta])* },
297 $record,
298 { $(#[$table_meta])* },
299 $table,
300 {
301 $($(#[$variant_meta])* $variant $(= $value)? as $field),+
302 }
303 }
304 };
305
306 (
307 @table
308 $len:expr,
309 { $(#[$name_meta:meta])* },
310 $name:ident,
311 { $(#[$table_meta:meta])* },
312 $table:ident,
313 $table_expr:ident {
314 $($(#[$variant_meta:meta])* $variant:ident $(= $value:tt)? as $field:tt),+ $(,)?
315 }
316 ) => {
317 $(#[$name_meta])*
318 #[repr(u8)]
319 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
320 pub enum $name {
321 $(
322 $(#[$variant_meta])*
323 $variant $(= $value)?
324 ),+
325 }
326
327 $(#[$table_meta])*
328 pub type $table<T = bool> = $crate::finite::Table<$name, T, $len>;
329
330 impl $crate::finite::FiniteSet<$len> for $name {
331 const ALL: [Self; $len] = [$(Self::$variant),+];
332 }
333
334 #[doc = concat!(stringify!($name), " Finite Set API.")]
335 impl $name {
336 pub const LEN: usize = $len;
337
338 pub const ALL: [Self; $len] = <Self as $crate::finite::FiniteSet<$len>>::ALL;
339
340 #[inline]
341 pub const fn name(self) -> &'static str {
342 match self {
343 $(Self::$variant => $crate::finite_set!(@name $field)),+
344 }
345 }
346
347 #[inline]
348 pub const fn eq(self, other: Self) -> bool {
349 self as u8 == other as u8
350 }
351
352 #[inline]
353 pub const fn index(self) -> usize {
354 let mut index = 0;
355 while index < Self::ALL.len() {
356 if Self::ALL[index] as u8 == self as u8 {
357 return index;
358 }
359 index += 1;
360 }
361 unreachable!()
362 }
363
364 #[inline]
365 pub const fn from_index(index: u8) -> Option<Self> {
366 if index < Self::LEN as u8 {
367 Some(Self::panicky_from_index(index))
368 } else {
369 None
370 }
371 }
372
373 #[inline]
374 #[track_caller]
375 pub(crate) const fn panicky_from_index(index: u8) -> Self {
376 assert!(index < Self::LEN as u8);
377 Self::ALL[index as usize]
378 }
379
380 #[inline]
381 pub fn iter() -> impl Iterator<Item = Self> {
382 <Self as $crate::finite::FiniteSet<$len>>::iter()
383 }
384
385 #[inline]
386 pub fn iter_rev() -> impl Iterator<Item = Self> {
387 <Self as $crate::finite::FiniteSet<$len>>::iter_rev()
388 }
389 }
390
391 impl core::fmt::Display for $name {
392 #[inline]
393 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
394 f.write_str(self.name())
395 }
396 }
397
398 impl<T: Copy> $crate::finite::Table<$name, T, $len> {
399 #[inline]
400 pub const fn get(&self, key: $name) -> T {
401 self.all[key.index()]
402 }
403
404 #[inline]
405 pub const fn set(&mut self, key: $name, value: T) {
406 self.all[key.index()] = value;
407 }
408 }
409
410 impl<T> $crate::finite::Table<$name, T, $len> {
411 #[inline]
412 pub const fn get_ref(&self, key: $name) -> &T {
413 &self.all[key.index()]
414 }
415
416 #[inline]
417 pub const fn get_mut(&mut self, key: $name) -> &mut T {
418 &mut self.all[key.index()]
419 }
420 }
421
422 impl<T> core::ops::Index<$name> for $crate::finite::Table<$name, T, $len> {
423 type Output = T;
424
425 #[inline]
426 fn index(&self, key: $name) -> &T {
427 &self.all[key.index()]
428 }
429 }
430
431 impl<T> core::ops::IndexMut<$name> for $crate::finite::Table<$name, T, $len> {
432 #[inline]
433 fn index_mut(&mut self, key: $name) -> &mut T {
434 &mut self.all[key.index()]
435 }
436 }
437 };
438
439 (
440 @record
441 $len:expr,
442 { $(#[$name_meta:meta])* },
443 $name:ident,
444 { $(#[$record_meta:meta])* },
445 $record:ident,
446 { $(#[$table_meta:meta])* },
447 $table:ident,
448 {
449 $($(#[$variant_meta:meta])* $variant:ident $(= $value:tt)? as $field:ident),+ $(,)?
450 }
451 ) => {
452 $crate::finite_set! {
453 @table
454 $len,
455 { $(#[$name_meta])* },
456 $name,
457 { $(#[$table_meta])* },
458 $table,
459 $table {
460 $($(#[$variant_meta])* $variant $(= $value)? as $field),+
461 }
462 }
463
464 $(#[$record_meta])*
465 #[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
466 pub struct $record<T = bool> {
467 $(
468 $(#[$variant_meta])*
469 pub $field: T
470 ),+
471 }
472
473 impl<T: Copy> $record<T> {
474 #[inline]
475 pub const fn get(&self, key: $name) -> T {
476 *self.get_ref(key)
477 }
478 }
479
480 impl<T> $record<T> {
481 #[inline]
482 pub const fn get_ref(&self, key: $name) -> &T {
483 match key {
484 $( $name::$variant => &self.$field ),+
485 }
486 }
487
488 #[inline]
489 pub const fn get_mut(&mut self, key: $name) -> &mut T {
490 match key {
491 $( $name::$variant => &mut self.$field ),+
492 }
493 }
494 }
495
496 impl<T: $crate::finite::Empty> $crate::finite::Empty for $record<T> {
497 const EMPTY: Self = Self {
498 $( $field: T::EMPTY ),+
499 };
500
501 fn is_empty(&self) -> bool {
502 $( self.$field.is_empty() )&&+
503 }
504 }
505
506 impl<T> core::ops::Index<$name> for $record<T> {
507 type Output = T;
508
509 #[inline]
510 fn index(&self, key: $name) -> &T {
511 self.get_ref(key)
512 }
513 }
514
515 impl<T> core::ops::IndexMut<$name> for $record<T> {
516 #[inline]
517 fn index_mut(&mut self, key: $name) -> &mut T {
518 self.get_mut(key)
519 }
520 }
521 };
522
523 (
524 @cursor
525 $len:expr,
526 $name:ident,
527 $cursor:ident
528 ) => {
529 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
530 pub struct $cursor {
531 next: u8,
532 }
533
534 impl $name {
535 #[inline]
536 pub const fn cursor() -> $cursor {
537 $cursor { next: 0 }
538 }
539 }
540
541 impl $cursor {
542 #[inline]
543 pub const fn next(&mut self) -> Option<$name> {
544 if self.done() {
545 None
546 } else {
547 let value = $name::panicky_from_index(self.next);
548 self.next += 1;
549 Some(value)
550 }
551 }
552
553 #[inline]
554 pub const fn skip(&mut self, n: u8) -> bool {
555 let Some(next) = self.next.checked_add(n) else {
556 return false;
557 };
558 if next > $len as u8 {
559 return false;
560 }
561 self.next = next;
562 true
563 }
564
565 #[inline]
566 pub const fn done(self) -> bool {
567 self.next >= $len as u8
568 }
569 }
570 };
571
572 (@count $($variant:ident),+) => {
573 <[()]>::len(&[$($crate::finite_set!(@unit $variant)),+])
574 };
575
576 (@unit $variant:ident) => {
577 ()
578 };
579
580 (@name $field:ident) => {
581 stringify!($field)
582 };
583
584 (@name $field:literal) => {
585 $field
586 };
587}
588
589#[macro_export]
590macro_rules! finite_for {
594 ($value:ident in $set:ty $body:block) => {{
595 let all = <$set>::ALL;
596 let mut index = 0usize;
597 while index < all.len() {
598 let $value = all[index];
599 $body
600 index += 1;
601 }
602 }};
603}
604
605