derive_asref 0.1.0

derive AsRef in variety way.
Documentation
use crate::attrs::Attribute;
use std::convert::TryFrom;

pub struct Struct {
    pub ident: syn::Ident,
    pub attrs: Vec<Attribute>,
    pub fields: Vec<Field>,
}

impl TryFrom<syn::DeriveInput> for Struct {
    type Error = syn::Error;

    fn try_from(origin: syn::DeriveInput) -> syn::Result<Struct> {
        let data = match &origin.data {
            syn::Data::Struct(ref data) => data,
            _ => return Err(syn::Error::new_spanned(&origin, "is not a struct")),
        };

        let fields = match &data.fields {
            syn::Fields::Named(ref fields) => fields
                .named
                .iter()
                .cloned()
                .map(Field::try_from)
                .collect::<Result<Vec<_>, _>>()?,
            syn::Fields::Unnamed(ref fields) => fields
                .unnamed
                .iter()
                .cloned()
                .map(Field::try_from)
                .collect::<Result<Vec<_>, _>>()?,
            syn::Fields::Unit => {
                return Err(syn::Error::new_spanned(origin.ident, "There is no field"))
            }
        };

        let attrs = origin
            .attrs
            .iter()
            .map(|attr| Attribute::try_from(attr.clone()))
            .collect::<Result<Vec<_>, _>>()?;

        Ok(Struct {
            ident: origin.ident,
            attrs,
            fields,
        })
    }
}

pub struct Field {
    pub ident: syn::Ident,
    pub attrs: Vec<Attribute>,
}

impl TryFrom<syn::Field> for Field {
    type Error = syn::Error;

    fn try_from(origin: syn::Field) -> syn::Result<Field> {
        let attrs = origin
            .attrs
            .iter()
            .map(|attr| Attribute::try_from(attr.clone()))
            .collect::<Result<Vec<_>, _>>()?;

        let ident = origin.ident.clone().ok_or(syn::Error::new_spanned(
            &origin,
            "We only support named field",
        ))?;

        Ok(Field { attrs, ident })
    }
}