1#[macro_export]
22macro_rules! convertible_enum {
23 (#[repr($type:ty)]$(#[$meta:meta])* $visibility:vis enum $enum_name:ident {
24 $($(#[$variant_meta:meta])* $variant_name:ident = $variant_value:expr,)*
25 }) => {
26 #[repr($type)]
27 $(#[$meta])*
28 $visibility enum $enum_name {
29 $($(#[$variant_meta])* $variant_name = $variant_value,)*
30 Unknown($type)
31 }
32
33 impl std::convert::From<$type> for $enum_name {
34 fn from(v: $type) -> Self {
35 if false { unreachable!() }
36 $( else if v == $variant_value { Self::$variant_name } )*
37 else { Self::Unknown(v) }
38 }
39 }
40
41 impl std::convert::From<$enum_name> for $type {
42 fn from(value: $enum_name) -> $type {
43 match value {
44 $($enum_name::$variant_name => $variant_value,)*
45 $enum_name::Unknown(other) => other,
46 }
47 }
48 }
49 }
50}
51
52#[macro_export]
73macro_rules! maybe_convertible_enum {
74 (#[repr($type:ty)]$(#[$meta:meta])* $visibility:vis enum $enum_name:ident {
75 $($(#[$variant_meta:meta])* $variant_name:ident = $variant_value:expr,)*
76 }) => {
77 #[repr($type)]
78 $(#[$meta])*
79 $visibility enum $enum_name {
80 $($(#[$variant_meta])* $variant_name = $variant_value,)*
81 }
82
83 paste::paste! {
84 #[derive(Debug, PartialEq, Eq)]
85 pub struct [<Unknown $enum_name ValueError>](pub $type);
86
87 impl std::fmt::Display for [<Unknown $enum_name ValueError>] {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 write!(f, concat!("Enum '", stringify!($enum_name), "' has no variant with value '{}'"), self.0)
90 }
91 }
92
93 impl std::error::Error for [<Unknown $enum_name ValueError>] {}
94
95 impl std::convert::TryFrom<$type> for $enum_name {
97 type Error = [<Unknown $enum_name ValueError>];
98 fn try_from(v: $type) -> Result<Self, Self::Error> {
99 match v {
100 $($variant_value => Ok(Self::$variant_name),)*
101 other => Err([<Unknown $enum_name ValueError>](other)),
102 }
103 }
104 }
105 }
106
107 impl From<$enum_name> for $type {
109 fn from(v: $enum_name) -> $type {
110 match v {
111 $($enum_name::$variant_name => $variant_value,)*
112 }
113 }
114 }
115 }
116}
117
118pub use {convertible_enum, maybe_convertible_enum};