forgejo-api-types/src/macros.rs

113 lines
3.9 KiB
Rust

// 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<E>(self, v: bool) -> Result<Self::Value, E>
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<D>(deserializer: D) -> Result<Self, D::Error>
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");
}
}
}
};
}