use crate::{FromStrDebug, ProcMacro, TokenTree};
use std::{fmt::Display, iter, str::FromStr};
pub trait TokenStream:
ProcMacro
+ Default
+ Display
+ Extend<Self::TokenStream>
+ Extend<Self::TokenTree>
+ From<Self::TokenTree>
+ FromIterator<Self::TokenStream>
+ FromIterator<Self::TokenTree>
+ FromStr
+ IntoIterator<IntoIter = Self::TokenStreamIntoIter, Item = Self::TokenTree>
{
fn new() -> Self;
fn is_empty(&self) -> bool;
}
pub trait TokenStreamExt:
crate::ProcMacroExt<TokenStreamExt = Self> + TokenStream + FromStrDebug
{
#[inline]
#[must_use]
fn apply_span(self, span: Self::Span) -> Self {
self.into_iter()
.map(|mut tt| {
tt.set_span(span);
tt
})
.collect()
}
#[inline]
#[must_use]
fn expect(self, mut tokens: impl Iterator<Item = Self::TokenTree>) -> Option<(Self, Self)> {
let mut it = self.into_iter();
let mut n = 0;
'check: {
for a in it.clone() {
let Some(b) = tokens.next() else { break 'check };
n += 1;
if a.to_string() != b.to_string() {
return None;
}
}
if tokens.next().is_some() {
return None;
}
}
let mut matched = Self::new();
while n != 0 {
n -= 1;
matched.extend(iter::once(it.next().unwrap()))
}
Some((matched, Self::from_iter(it)))
}
}
macro_rules! impl_token_stream {
($($pm:ident: $feature:literal),*) => { $(
#[cfg(feature = $feature)]
impl TokenStream for $pm::TokenStream {
#[inline]
fn new() -> Self {
Self::new()
}
#[inline]
fn is_empty(&self) -> bool {
self.is_empty()
}
}
#[cfg(feature = $feature)]
impl TokenStreamExt for $pm::TokenStream {}
#[cfg(feature = $feature)]
impl crate::ToTokenStream<$pm::TokenStream> for $pm::TokenStream {
#[inline]
fn extend_token_stream(&self, ts: &mut $pm::TokenStream) {
ts.extend(self.clone().into_iter())
}
#[inline]
fn into_token_stream(self) -> $pm::TokenStream {
self
}
#[inline]
fn to_token_stream(&self) -> $pm::TokenStream {
self.clone()
}
}
)* };
}
impl_token_stream!(proc_macro: "proc-macro", proc_macro2: "proc-macro2");