cgp-macro-lib 0.6.1

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

use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::token::{Bracket, Comma, For, Lt, Semi};
use syn::{Ident, Type, braced, bracketed};

use crate::parse::{DelegateMode, ImplGenerics};

pub struct DelegateAndCheckSpec {
    pub impl_generics: ImplGenerics,
    pub trait_name: Ident,
    pub context_type: Type,
    pub provider_type: Type,
    pub entries: Punctuated<DelegateAndCheckEntry, Comma>,
}

#[derive(Clone)]
pub struct DelegateAndCheckEntry {
    pub keys: Punctuated<Type, Comma>,
    pub mode: DelegateMode,
    pub value: Type,
}

impl Parse for DelegateAndCheckSpec {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let impl_generics = if input.peek(Lt) {
            input.parse()?
        } else {
            Default::default()
        };

        let trait_name = input.parse()?;

        let _: For = input.parse()?;

        let context_type = input.parse()?;

        let _: Semi = input.parse()?;

        let provider_type = input.parse()?;

        let entries = {
            let body;
            braced!(body in input);
            Punctuated::parse_terminated(&body)?
        };

        Ok(Self {
            impl_generics,
            trait_name,
            context_type,
            provider_type,
            entries,
        })
    }
}

impl Parse for DelegateAndCheckEntry {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let keys = if input.peek(Bracket) {
            let body;
            bracketed!(body in input);
            Punctuated::parse_terminated(&body)?
        } else {
            let key: Type = input.parse()?;
            Punctuated::from_iter(iter::once(key))
        };

        let mode = input.parse()?;

        let value = input.parse()?;

        Ok(Self { keys, mode, value })
    }
}