pumpkinplus/mirror_types/macros.rs
1/// Generates a mirror enum with serde, Display, matches_config, and From impls.
2///
3/// # Usage
4/// ```
5/// mirror_enum! {
6/// pub enum GameMode from pumpkin_plugin_api::player::GameMode {
7/// Survival,
8/// Creative,
9/// Adventure,
10/// Spectator,
11/// }
12/// }
13/// ```
14///
15/// This produces:
16/// - An enum with `Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash`
17/// - `#[serde(rename_all = "PascalCase")]`
18/// - `matches_config(&self, allowed: &[Self]) -> bool`
19/// - `Display` via `Debug` representation
20/// - `From<upstream>` with a catch-all fallback to the first variant
21#[macro_export]
22macro_rules! mirror_enum {
23 (
24 $(#[$meta:meta])*
25 $vis:vis enum $name:ident from $upstream:path {
26 $first:ident,
27 $($variant:ident),* $(,)?
28 }
29 ) => {
30 $(#[$meta])*
31 #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash)]
32 #[serde(rename_all = "PascalCase")]
33 $vis enum $name {
34 $first,
35 $($variant),*
36 }
37
38 impl $name {
39 /// Returns true if the given list is empty (allow-all) or contains this variant.
40 pub fn matches_config(&self, allowed: &[Self]) -> bool {
41 allowed.is_empty() || allowed.contains(self)
42 }
43 }
44
45 impl std::fmt::Display for $name {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 write!(f, "{:?}", self)
48 }
49 }
50
51 impl From<$upstream> for $name {
52 fn from(value: $upstream) -> Self {
53 #[allow(unreachable_patterns)]
54 match value {
55 <$upstream>::$first => Self::$first,
56 $(<$upstream>::$variant => Self::$variant,)*
57 _ => Self::$first,
58 }
59 }
60 }
61 };
62}