1pub trait ValuedEnum<T> where Self: Sized {
2 fn equal(&self, other: &T) -> bool;
3
4 fn key(&self) -> &str;
5 fn value(self) -> T;
6 fn ref_value(&self) -> &T;
7
8 fn keys() -> Vec<&'static str>;
9 fn values() -> Vec<T>;
10 fn variants() -> Vec<Self>;
11
12 fn from_key(key: &str) -> Option<Self>;
13 fn from_value(value: &T) -> Option<Self>;
14}
15
16
17#[macro_export]
18macro_rules! py_enum {
19 {
20 $(#[$meta:meta])*
21 $name:ident ( $valtype:ty ):
22 $(
23 $(#[$item_meta:meta])*
24 $id:ident = $val:expr
25 )*
26 $(,)?
27 } => {
28 $crate::valued_enum! {
29 $(#[$meta])*
30 pub enum $name ($valtype) {
31 $(
32 $(#[$item_meta])*
33 pub $id = $val,
34 )*
35 }
36 }
37 }
38}
39
40#[macro_export]
41macro_rules! rust_enum {
42 {
43 $(#[$meta:meta])*
44 $e_vis:vis enum $name:ident ( $valtype:ty ) {
45 $(
46 $(#[$item_meta:meta])*
47 $id:ident = $val:expr,
48 )*
49 $(,)?
50 }
51 } => {
52 $crate::valued_enum! {
53 $(#[$meta])*
54 $e_vis enum $name ($valtype) {
55 $(
56 $(#[$item_meta])*
57 pub $id = $val,
58 )*
59 }
60 }
61 }
62}
63
64#[macro_export]
65macro_rules! valued_enum {
66 {
67 $(#[$meta:meta])*
68 $e_vis:vis enum $name:ident ( $valtype:ty ) {
69 $(
70 $(#[$item_meta:meta])*
71 $i_vis:vis $id:ident = $val:expr,
72 )*
73 $(,)?
74 }
75 } => {
76 $(#[$meta])*
77 $e_vis struct $name(&'static str, $valtype);
78
79 impl $name {
80 $(
81 $(#[$item_meta])*
82 $i_vis const $id: $name = $name(stringify!($id), $val);
83 )*
84 }
85
86 impl $crate::ValuedEnum<$valtype> for $name {
87 fn equal(&self, other: &$valtype) -> bool {
88 &self.1 == other
89 }
90
91 fn key(&self) -> &str {
92 self.0
93 }
94
95 fn value(self) -> $valtype {
96 self.1
97 }
98
99 fn ref_value(&self) -> &$valtype {
100 &self.1
101 }
102
103 fn keys() -> Vec<&'static str> {
104 vec![
105 $( $name::$id.key(), )*
106 ]
107 }
108
109 fn values() -> Vec<$valtype> {
110 vec![
111 $( $name::$id.value(), )*
112 ]
113 }
114
115 fn variants() -> Vec<$name> {
116 vec![
117 $( $name::$id, )*
118 ]
119 }
120
121 fn from_key(key: &str) -> Option<Self> {
122 $( if $name::$id.key() == key { return Some($name::$id) } )*
123
124 None
125 }
126
127 fn from_value(value: &$valtype) -> Option<Self> {
128 $( if $name::$id.equal(value) { return Some($name::$id) } )*
129
130 None
131 }
132 }
133 };
134}