use std::{fmt, panic::Location, str::FromStr};
use proc_macro::{Span, TokenStream};
use crate::{IntoTokens, PushToken, TokenQueue};
#[derive(Debug, Clone, Copy)]
pub struct Verbatim {
text: &'static str,
kind: VerbatimKind,
location: &'static Location<'static>,
span: Option<Span>,
}
#[derive(Debug, Clone, Copy)]
pub enum VerbatimKind {
Ident,
Literal,
Lifetime,
}
impl fmt::Display for VerbatimKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
VerbatimKind::Ident => "identifier",
VerbatimKind::Literal => "literal",
VerbatimKind::Lifetime => "lifetime",
};
f.write_str(s)
}
}
impl Verbatim {
#[doc(hidden)]
#[track_caller]
pub const fn new(text: &'static str, kind: VerbatimKind) -> Verbatim {
Verbatim {
text,
kind,
location: Location::caller(),
span: None,
}
}
pub const fn with_span(mut self, span: Span) -> Verbatim {
self.span = Some(span);
self
}
}
impl IntoTokens for Verbatim {
fn extend_tokens(self, q: &mut TokenQueue) {
let Verbatim {
text,
kind,
location,
span,
} = self;
let ts = TokenStream::from_str(text).unwrap_or_else(move |lex| {
panic!("failed to reparse {kind} {text:?} {location}: {lex}")
});
match span {
None => q.push(ts),
Some(span) => {
for mut tt in ts {
tt.set_span(span);
q.push(tt)
}
}
};
}
}
impl PushToken for Verbatim {}