moxy-derive 0.0.1

derive macros for moxy crate
Documentation
use quote::quote;

use crate::core::Attrs;

#[derive(Clone)]
pub struct Field {
    attrs: Attrs,
    vis: syn::Visibility,
    name: FieldName,
    ty: syn::Type,
}

impl Field {
    pub fn parse(i: usize, field: &syn::Field) -> syn::Result<Self> {
        Ok(Self {
            attrs: Attrs::parse(&field.attrs)?,
            vis: field.vis.clone(),
            name: match &field.ident {
                None => syn::Index::from(i).into(),
                Some(v) => v.clone().into(),
            },
            ty: field.ty.clone(),
        })
    }

    pub fn attrs(&self) -> &Attrs {
        &self.attrs
    }

    pub fn vis(&self) -> &syn::Visibility {
        &self.vis
    }

    pub fn name(&self) -> &FieldName {
        &self.name
    }

    pub fn ty(&self) -> &syn::Type {
        &self.ty
    }

    pub fn display_name(&self) -> String {
        let display = self.attrs.get("display");

        display
            .iter()
            .find_map(|a| a.as_attr())
            .and_then(|attr| {
                attr.args().iter().find_map(|arg| {
                    if arg.path().is_ident("alias") {
                        arg.as_lit().and_then(|lit| match lit {
                            syn::Lit::Str(s) => Some(s.value()),
                            _ => None,
                        })
                    } else {
                        None
                    }
                })
            })
            .unwrap_or_else(|| self.name.to_string())
    }
}

impl quote::ToTokens for Field {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        let attrs = self.attrs();
        let vis = self.vis();
        let name = self.name();
        let ty = self.ty();

        tokens.extend(quote! {
            #[#attrs] #vis #name : #ty,
        });
    }
}

#[derive(Clone, PartialEq, Eq)]
pub enum FieldName {
    Index(syn::Index),
    Ident(syn::Ident),
}

impl FieldName {
    #[allow(unused)]
    pub fn is_index(&self) -> bool {
        matches!(self, Self::Index(_))
    }

    #[allow(unused)]
    pub fn is_ident(&self) -> bool {
        matches!(self, Self::Ident(_))
    }
}

impl From<syn::Index> for FieldName {
    fn from(value: syn::Index) -> Self {
        Self::Index(value)
    }
}

impl From<syn::Ident> for FieldName {
    fn from(value: syn::Ident) -> Self {
        Self::Ident(value)
    }
}

impl quote::ToTokens for FieldName {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        tokens.extend(match self {
            Self::Index(v) => quote!(#v),
            Self::Ident(v) => quote!(#v),
        });
    }
}

impl std::fmt::Display for FieldName {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Ident(v) => write!(f, "{}", v),
            Self::Index(v) => write!(f, "{}", v.index),
        }
    }
}