blaze_common/
enums.rs

1#[macro_export]
2macro_rules! unit_enum_from_str {
3    ($iterable_type:ty) => {
4        impl std::str::FromStr for $iterable_type {
5            type Err = $crate::error::Error;
6
7            fn from_str(value: &str) -> $crate::error::Result<$iterable_type> {
8                let lowercase_value = value.to_ascii_lowercase();
9                <$iterable_type as strum::IntoEnumIterator>::iter()
10                    .find(|t| t.to_string().to_ascii_lowercase() == lowercase_value)
11                    .ok_or_else(|| {
12                        anyhow::anyhow!(
13                            "could not convert \"{}\" to a valid {}, possible values are [{}].",
14                            value,
15                            stringify!($iterable_type),
16                            <$iterable_type as strum::IntoEnumIterator>::iter()
17                                .map(|t| t.to_string())
18                                .collect::<Vec<_>>()
19                                .join(", ")
20                        )
21                    })
22            }
23        }
24    };
25}
26
27#[macro_export]
28macro_rules! unit_enum_deserialize {
29    ($iterable_type:ty) => {
30        impl <'de> serde::de::Deserialize<'de> for $iterable_type {
31            fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
32                where
33                    D: serde::Deserializer<'de> {
34
35                $crate::paste::paste! {
36
37                    struct [<$iterable_type Visitor>];
38
39                    impl serde::de::Visitor<'_> for [<$iterable_type Visitor>] {
40
41                        type Value = $iterable_type;
42
43                        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
44                            formatter.write_str(&format!(
45                                "one of: {}",
46                                <$iterable_type as strum::IntoEnumIterator>::iter()
47                                    .map(|variant| variant.to_string())
48                                    .collect::<Vec<_>>()
49                                    .join(", ")
50                            ))
51                        }
52
53                        fn visit_str<E>(self, v: &str) -> std::result::Result<Self::Value, E>
54                            where
55                                E: serde::de::Error, {
56                            <$iterable_type as std::str::FromStr>::from_str(v).map_err(|from_str_err| {
57                                E::custom(from_str_err.to_string())
58                            })
59                        }
60                    }
61
62                    deserializer.deserialize_str([<$iterable_type Visitor>])
63                }
64            }
65        }
66    }
67}
68
69pub use {unit_enum_deserialize, unit_enum_from_str};