satay-codegen 0.1.2

Generate Rust client code from OpenAPI 3.1 documents
Documentation
use crate::model::EnumVariant;

use super::super::{doc_attrs, ident, lit_str};

pub(super) fn render_enum(
    name: &str,
    description: Option<&str>,
    variants: &[EnumVariant],
) -> Vec<syn::Item> {
    let name = ident(name);
    let docs = doc_attrs(description);
    let variant_defs = variants.iter().map(render_enum_variant).collect::<Vec<_>>();
    let as_str_arms = variants
        .iter()
        .map(render_enum_as_str_arm)
        .collect::<Vec<_>>();

    let enum_item = syn::parse_quote!(
        #(#docs)*
        #[derive(Debug, Clone, PartialEq, Eq, Default)]
        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
        pub enum #name {
            #(#variant_defs),*,
            #[default]
            #[cfg_attr(feature = "serde", serde(other))]
            Unknown,
        }
    );
    let inherent_impl = syn::parse_quote!(
        impl #name {
            pub const fn as_str(&self) -> &'static str {
                match self {
                    #(#as_str_arms)*
                    Self::Unknown => "",
                }
            }
        }
    );
    let as_ref_impl = syn::parse_quote!(
        impl AsRef<str> for #name {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }
    );
    let display_impl = syn::parse_quote!(
        impl fmt::Display for #name {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.write_str(self.as_str())
            }
        }
    );

    vec![enum_item, inherent_impl, as_ref_impl, display_impl]
}

fn render_enum_variant(variant: &EnumVariant) -> syn::Variant {
    let name = ident(&variant.rust_name);
    if variant.rust_name == variant.wire_name {
        syn::parse_quote!(#name)
    } else {
        let wire_name = lit_str(&variant.wire_name);
        syn::parse_quote!(#[cfg_attr(feature = "serde", serde(rename = #wire_name))] #name)
    }
}

fn render_enum_as_str_arm(variant: &EnumVariant) -> syn::Arm {
    let name = ident(&variant.rust_name);
    let wire_name = lit_str(&variant.wire_name);
    syn::parse_quote!(Self::#name => #wire_name,)
}