fn expand_systemd_enum()

in metalos/lib/systemd/macros.rs [7:105]


fn expand_systemd_enum(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
    let name = input.ident.clone();
    match input.data {
        Data::Enum(e) => {
            let to_strs = e.variants.iter().map(|v| {
                let i = v.ident.clone();
                let name = i.to_string().to_case(Case::Kebab);
                match name.as_str() {
                    "unknown" => match v.fields {
                        Fields::Unit => quote! {
                            Self::Unknown => "unknown"
                        },
                        _ => quote! {
                            Self::Unknown(v) => v,
                        },
                    },
                    _ => quote! {
                        Self::#i => #name,
                    },
                }
            });
            let from_strs = e.variants.iter().map(|v| {
                let i = v.ident.clone();
                let name = i.to_string().to_case(Case::Kebab);
                match name.as_str() {
                    "unknown" => match v.fields {
                        Fields::Unit => quote! {
                            _ => Self::Unknown,
                        },
                        _ => quote! {
                            value => Ok(Self::Unknown(value.to_owned())),
                        },
                    },
                    _ => quote! {
                        #name => Ok(Self::#i),
                    },
                }
            });
            Ok(quote! {
                impl ::zvariant::Type for #name {
                    fn signature() -> ::zvariant::Signature<'static> {
                        <String as ::zvariant::Type>::signature()
                    }
                }

                impl ::std::str::FromStr for #name {
                    type Err = ::zvariant::Error;
                    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
                        match s {
                            #(#from_strs)*
                            _ => Err(::zvariant::Error::Message(format!("Unknown variant {}", s))),
                        }
                    }
                }

                impl ::std::fmt::Display for #name {
                    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                        let s = match self {
                            #(#to_strs)*
                        };
                        write!(f, "{}", s)
                    }
                }

                impl<'de> ::serde::Deserialize<'de> for #name {
                    fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
                    where D: ::serde::Deserializer<'de> {
                        let s: String = ::serde::Deserialize::deserialize(deserializer)?;
                        s.parse().map_err(::serde::de::Error::custom)
                    }
                }

                impl ::serde::Serialize for #name {
                    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
                    where S: ::serde::Serializer {
                        serializer.serialize_str(&self.to_string())
                    }
                }

                impl<'v> ::std::convert::TryFrom<::zvariant::Value<'v>> for #name {
                    type Error = ::zvariant::Error;

                    fn try_from(v: ::zvariant::Value<'v>) -> ::zvariant::Result<Self> {
                        String::try_from(v).and_then(|v| v.parse())
                    }
                }

                impl ::std::convert::TryFrom<::zvariant::OwnedValue> for #name {
                    type Error = ::zvariant::Error;

                    fn try_from(v: ::zvariant::OwnedValue) -> ::zvariant::Result<Self> {
                        String::try_from(v).and_then(|v| v.parse())
                    }
                }
            })
        }
        _ => Err(Error::new(input.span(), "not enum")),
    }
}