// Define the macro that generates the implementation for the enum #[macro_export] macro_rules! implement_boolean_enum { ($module_name:ident, $enum_name:ident) => { implement_boolean_enum!($module_name, $enum_name { Yes, No }); }; ($module_name:ident, $enum_name:ident { $yes_variant:ident, $no_variant:ident }) => { pub mod $module_name { use clap::ValueEnum; use strum::{Display, EnumIs, EnumIter, EnumString}; #[derive( Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Display, EnumIter, EnumString, EnumIs, )] pub enum $enum_name { $yes_variant, $no_variant, } mod serde { use serde::de::Visitor; use serde::{Deserialize, Serialize}; use super::$enum_name; impl Serialize for $enum_name { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { serializer.serialize_bool(matches!(*self, $enum_name::$yes_variant)) } } struct PrivateVisitor; impl<'de> Visitor<'de> for PrivateVisitor { type Value = $enum_name; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("a boolean value (true/false)") } fn visit_bool(self, v: bool) -> Result where E: serde::de::Error, { if v { Ok($enum_name::$yes_variant) } else { Ok($enum_name::$no_variant) } } } impl<'de> Deserialize<'de> for $enum_name { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { deserializer.deserialize_bool(PrivateVisitor) } } } mod from { use super::$enum_name; impl From<$enum_name> for bool { fn from(val: $enum_name) -> Self { match val { $enum_name::$yes_variant => true, $enum_name::$no_variant => false, } } } } #[cfg(test)] mod tests { use super::$enum_name; #[test] fn deserialize_true() { let input = "true"; let val: $enum_name = serde_json::from_str(input).unwrap(); assert_eq!($enum_name::$yes_variant, val); } #[test] fn deserialize_false() { let input = "false"; let val: $enum_name = serde_json::from_str(input).unwrap(); assert_eq!($enum_name::$no_variant, val); } #[test] fn serialize_true() { let input = $enum_name::$yes_variant; let val = serde_json::to_string(&input).unwrap(); assert_eq!(val.as_str(), "true"); } #[test] fn serialize_false() { let input = $enum_name::$no_variant; let val = serde_json::to_string(&input).unwrap(); assert_eq!(val.as_str(), "false"); } } } }; }