darling_core 0.24.0

Helper crate for proc-macro library for reading attributes into structs when implementing custom derives. Use https://crates.io/crates/darling in your code.
Documentation
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};

use crate::{
    codegen::{ExtractAttribute, OuterFromImpl, TraitImpl},
    util::PathList,
};

use super::ForwardAttrs;

pub struct FromAttributesImpl<'a> {
    pub base: TraitImpl<'a>,
    pub attr_names: &'a PathList,
    pub forward_attrs: ForwardAttrs<'a>,
}

impl ToTokens for FromAttributesImpl<'_> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let ty_ident = self.base.ident;
        let input = self.param_name();
        let post_transform = self.base.post_transform_call();

        if let Some((member, _)) = self
            .base
            .data
            .as_struct()
            .and_then(|fields| super::extract_transparent(fields, self.base.transparent))
        {
            self.wrap(
                quote! {
                    fn from_attributes(#input: &[_darling::export::syn::Attribute]) -> _darling::Result<Self> {
                        _darling::export::Ok(
                            #ty_ident { #member: _darling::FromAttributes::from_attributes(#input)? }
                        ) #post_transform
                    }
                },
                tokens,
            );

            return;
        };

        let forwarded_fields = vec![self.forward_attrs.to_field_value()]
            .into_iter()
            .flatten();

        let inits = self.base.initializers();
        let default = self.base.fallback_decl();

        let grab_attrs = self.extractor();

        let declare_errors = self.base.declare_errors();
        let require_fields = self.base.require_fields();
        let check_errors = self.base.check_errors();

        self.wrap(
            quote! {
                fn from_attributes(#input: &[_darling::export::syn::Attribute]) -> _darling::Result<Self> {
                    #declare_errors

                    #grab_attrs

                    #require_fields

                    #check_errors

                    #default

                    _darling::export::Ok(#ty_ident {
                        #(#forwarded_fields,)*
                        #inits
                    }) #post_transform
                }
            },
            tokens,
        );
    }
}

impl ExtractAttribute for FromAttributesImpl<'_> {
    fn local_declarations(&self) -> TokenStream {
        self.base.local_declarations()
    }

    fn attr_names(&self) -> &PathList {
        self.attr_names
    }

    fn forward_attrs(&self) -> &super::ForwardAttrs<'_> {
        &self.forward_attrs
    }

    fn param_name(&self) -> TokenStream {
        quote!(__di)
    }

    fn attrs_accessor(&self) -> TokenStream {
        self.param_name()
    }

    fn core_loop(&self) -> TokenStream {
        self.base.core_loop()
    }
}

impl<'a> OuterFromImpl<'a> for FromAttributesImpl<'a> {
    fn trait_path(&self) -> syn::Path {
        path!(_darling::FromAttributes)
    }

    fn trait_bound(&self) -> syn::Path {
        path!(_darling::FromMeta)
    }

    fn base(&'a self) -> &'a TraitImpl<'a> {
        &self.base
    }
}