multiconst_proc_macros 0.2.2

implementation detail of multiconst
Documentation
use used_proc_macro::{
    Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};

use core::fmt::Display;

use alloc::{
    string::{String, ToString},
    vec,
    vec::Vec,
};

use crate::{
    syntax::{Crate, Spans},
    utils::{TokenStreamExt, WithSpan},
};

#[derive(Debug)]
pub(crate) struct Error {
    messages: Vec<CompileError>,
}

#[derive(Debug)]
struct CompileError {
    spans: Spans,
    msg: String,
}

impl Error {
    pub(crate) fn new<T: Display>(spans: Spans, msg: T) -> Self {
        Error {
            messages: vec![CompileError {
                spans,
                msg: msg.to_string(),
            }],
        }
    }
    pub(crate) fn with_span<T: Display>(span: Span, msg: T) -> Self {
        Self::new(
            Spans {
                start: span,
                end: span,
            },
            msg,
        )
    }

    #[allow(dead_code)]
    pub(crate) fn join(mut self, mut other: Error) -> Error {
        self.messages.append(&mut other.messages);
        self
    }

    pub(crate) fn to_compile_error(&self, crate_kw: &Crate) -> TokenStream {
        self.messages
            .iter()
            .map(|CompileError { spans, msg }| {
                TokenStream::from_array([
                    TokenTree::Ident(crate_kw.ident.clone().with_span(spans.start)),
                    Punct::new(':', Spacing::Joint)
                        .with_span(spans.start)
                        .into(),
                    Punct::new(':', Spacing::Alone)
                        .with_span(spans.start)
                        .into(),
                    TokenTree::Ident(Ident::new("__", spans.start)),
                    Punct::new(':', Spacing::Joint)
                        .with_span(spans.start)
                        .into(),
                    Punct::new(':', Spacing::Alone)
                        .with_span(spans.start)
                        .into(),
                    TokenTree::Ident(Ident::new("compile_error", spans.start)),
                    Punct::new('!', Spacing::Alone)
                        .with_span(spans.start)
                        .into(),
                    {
                        let x = Literal::string(msg).with_span(spans.end);
                        let x = TokenTree::Literal(x);
                        let x = TokenStream::from(x);
                        let x = Group::new(Delimiter::Brace, x);
                        x.with_span(spans.end).into()
                    },
                ])
            })
            .collect()
    }
}