#[macro_export]
macro_rules! roster {
(
$(#[$note:meta])*
$vis:vis enum $name:ident {
$( $(#[$row:meta])* $variant:ident = $declared:literal ),+ $(,)?
}
) => {
$(#[$note])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
$vis enum $name {
$( $(#[$row])* $variant, )+
}
impl $name {
$vis const ALL: &'static [Self] = &[$( Self::$variant ),+];
#[must_use]
$vis const fn name(self) -> &'static str {
match self {
$( Self::$variant => $declared, )+
}
}
}
};
}
#[macro_export]
macro_rules! kinds {
(
set = $set:ident;
dispositions = $record:ident;
$(
$(#[$note:meta])*
$kind:ident = $declared:literal, $seat:ident => $content:ty, $role:ty, $question:ty
);+ $(;)?
) => {
$(
$(#[$note])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct $kind;
impl $crate::kind::Kind for $kind {
const NAME: &'static str = $declared;
type Content = $content;
type Role = $role;
type Question = $question;
}
)+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum $set {
$( $(#[$note])* $kind ),+
}
impl $set {
pub const ALL: &'static [Self] = &[$( Self::$kind ),+];
#[must_use]
pub const fn name(self) -> &'static str {
match self {
$( Self::$kind => <$kind as $crate::kind::Kind>::NAME ),+
}
}
}
impl $crate::kind::KindSet for $set {
type Dispositions = $record;
const NAMES: &'static [&'static str] =
&[$( <$kind as $crate::kind::Kind>::NAME ),+];
}
#[must_use = "a disposition record is what happened to every kind of the set"]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct $record {
$(
#[doc = concat!("What happened to the `", $declared, "` kind.")]
pub $seat: $crate::kind::Disposition
),+
}
impl $record {
#[must_use]
pub const fn under(&self, row: $set) -> &$crate::kind::Disposition {
match row {
$( $set::$kind => &self.$seat ),+
}
}
}
impl $crate::kind::DispositionRecord for $record {
fn into_dispositions(
self,
) -> impl Iterator<Item = (&'static str, $crate::kind::Disposition)> {
[$( (<$kind as $crate::kind::Kind>::NAME, self.$seat) ),+].into_iter()
}
}
};
}