forgejo-api-types 0.1.11

Rusty API types of the forgejo API
Documentation
// 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 strum::IntoEnumIterator;

                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)
                        }
                    }

                    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
                    where
                        E: serde::de::Error,
                    {
                        $enum_name::iter()
                            .find(|s| s.to_string().to_lowercase() == v.to_lowercase())
                            .ok_or(E::custom("not string"))
                    }
                }

                impl<'de> Deserialize<'de> for $enum_name {
                    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
                    where
                        D: serde::Deserializer<'de>,
                    {
                        deserializer.deserialize_any(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");
                }
            }
        }
    };
}

// Define the macro that generates the deserialization test for a API type
#[macro_export]
macro_rules! define_deserialize_test {
    ($api_type:ty, $path_to_data:expr) => {
        #[cfg(test)]
        mod tests {
            use super::*;
            #[test]
            fn deserialize() {
                let data = include_str!($path_to_data);
                let _: $api_type = serde_json::from_str(data).unwrap();
            }
        }
    };
}