multiconst_proc_macros 0.2.2

implementation detail of multiconst
Documentation
use used_proc_macro::{Punct, Spacing, TokenStream, TokenTree};

use crate::{
    syntax::{Attributes, Crate, FieldName},
    utils::{TokenStreamExt, WithSpan},
    Error,
};

pub(crate) fn field_macro_impl(input: TokenStream) -> Result<TokenStream, TokenStream> {
    let input = &mut crate::parsing::ParseBuffer::new(input);
    let crate_kw = Crate::parse(input).unwrap();
    (|| -> Result<TokenStream, Error> {
        let mut out = TokenStream::new();
        let field_ident = FieldName::parse(input)?;
        input.assert_empty()?;
        field_ident.to_token_stream(&crate_kw, &mut out);

        Ok(out)
    })()
    .map_err(|e| e.to_compile_error(&crate_kw))
}

pub(crate) fn field_name_aliases_macro_impl(
    input: TokenStream,
) -> Result<TokenStream, TokenStream> {
    let input = &mut crate::parsing::ParseBuffer::new(input);
    let crate_kw = Crate::parse(input).unwrap();

    let allows = "#[allow(non_camel_case_types)]"
        .parse::<TokenStream>()
        .unwrap();

    (|| -> Result<TokenStream, Error> {
        let mut out = TokenStream::new();

        while !input.is_empty() {
            let attrs = Attributes::parse(input);
            let vis = input.parse_vis();
            let ident = input.parse_ident()?;
            let span = ident.span();

            out.extend(allows.clone());
            out.extend(attrs.attrs);
            out.extend(vis);
            out.append_keyword("type", span);

            if matches!(input.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == '=') {
                let equals = input.parse_punct('=')?;
                let eq_span = equals.span();

                out.append_one(ident);
                out.append_one(equals);

                if input.is_empty() {
                    return Err(Error::with_span(eq_span, "expected field name after this"));
                }

                FieldName::parse(input)?.to_token_stream(&crate_kw, &mut out);
            } else {
                let field_ident = FieldName::from_ident(&ident);

                out.append_one(ident);
                out.append_one(Punct::new('=', Spacing::Alone).with_span(span));
                field_ident.to_token_stream(&crate_kw, &mut out);
            }
            out.append_one(Punct::new(';', Spacing::Alone).with_span(span));

            input.parse_opt_punct(',')?;
        }

        Ok(out)
    })()
    .map_err(|e| e.to_compile_error(&crate_kw))
}