cgp-macro-lib 0.7.0

Context-generic programming core component macros implemented as a library.
Documentation
use core::mem;

use syn::punctuated::Punctuated;
use syn::token::Comma;
use syn::{Attribute, TypeParamBound};

use crate::cgp_fn::UseTypeSpec;

pub fn parse_component_attributes(
    attributes: &mut Vec<Attribute>,
) -> syn::Result<ComponentAttributes> {
    let mut parsed_attributes = ComponentAttributes::default();

    let in_attributes = mem::take(attributes);

    for attribute in in_attributes.into_iter() {
        if let Some(ident) = attribute.path().get_ident() {
            if ident == "extend" {
                let extend_bound = attribute
                    .parse_args_with(Punctuated::<TypeParamBound, Comma>::parse_terminated)?;
                parsed_attributes.extend.extend(extend_bound);
            } else if ident == "use_type" {
                let use_type_specs = attribute
                    .parse_args_with(Punctuated::<UseTypeSpec, Comma>::parse_terminated)?;

                for use_type_spec in use_type_specs.iter() {
                    for type_ident in use_type_spec.type_idents.iter() {
                        if let Some(equals) = &type_ident.equals {
                            return Err(syn::Error::new_spanned(
                                equals,
                                "Type equality constraints cannot be used in component trait definition",
                            ));
                        }
                    }
                }

                parsed_attributes.use_type.extend(use_type_specs);
            } else {
                attributes.push(attribute);
            }
        } else {
            attributes.push(attribute);
        }
    }

    Ok(parsed_attributes)
}

#[derive(Default)]
pub struct ComponentAttributes {
    pub extend: Vec<TypeParamBound>,
    pub use_type: Vec<UseTypeSpec>,
}