core_extensions_proc_macros/macro_utils_shared/
cmp_ts.rs

1// For comparing token streams in a Comparable way
2
3#[allow(unused_imports)]
4use crate::{
5    used_proc_macro::{Delimiter, Punct, TokenStream, TokenTree},
6    mmatches,
7};
8
9use core::cmp::PartialEq;
10
11use alloc::{
12    string::{String, ToString},
13    vec::Vec,
14};
15
16
17pub(crate) enum Found {
18    Yes,
19    No,
20}
21
22
23pub(crate) enum ComparableTT {
24    Ident(String),
25    Punct(Punct),
26    Literal(String),
27    Group(ComparableGroup),
28}
29
30
31
32impl ComparableTT {
33    pub(crate) fn new(tt: TokenTree) -> Self {
34        match tt {
35            TokenTree::Ident(ident) => ComparableTT::Ident(ident.to_string()),
36            TokenTree::Punct(x) => ComparableTT::Punct(x),
37            TokenTree::Literal(x) => ComparableTT::Literal(x.to_string()),
38            TokenTree::Group(group) => {
39                let this = ComparableGroup{
40                    stream:  group.stream().into_iter().map(ComparableTT::new).collect(),
41                    delimiter: group.delimiter(),
42                };
43                ComparableTT::Group(this)
44            },
45        }
46    }
47
48    pub(crate) fn many<I>(iter: I) -> Vec<ComparableTT>
49    where
50        I: IntoIterator<Item = TokenTree>
51    {
52        iter.into_iter().map(ComparableTT::new).collect()
53    }
54}
55
56impl PartialEq<ComparableTT> for TokenTree {
57    fn eq(&self, other: &ComparableTT) -> bool {
58        match (self, other) {
59            (TokenTree::Ident(l), ComparableTT::Ident(r)) => l.to_string() == *r,
60            (TokenTree::Punct(l), ComparableTT::Punct(r)) => 
61                l.as_char() == r.as_char() && l.spacing() == r.spacing() ,
62            (TokenTree::Literal(l), ComparableTT::Literal(r)) => l.to_string() == *r,
63            (TokenTree::Group(l), ComparableTT::Group(r)) => {
64                l.stream().into_iter().eq(r.stream.iter()) &&
65                l.delimiter() == r.delimiter
66            }
67            _ => false,
68        }
69    }
70}
71
72impl PartialEq<&ComparableTT> for TokenTree {
73    fn eq(&self, other: &&ComparableTT) -> bool {
74        *self == **other
75    }
76}
77
78
79pub(crate) struct ComparableGroup {
80    pub(crate) stream: Vec<ComparableTT>,
81    pub(crate) delimiter: Delimiter,
82}
83
84
85pub(crate) fn skip_until_match<I>(mut iter: I, s_tokens: &[ComparableTT]) -> (TokenStream, Found) 
86where 
87    I: Iterator<Item = TokenTree>
88{
89    let mut cmp_iter = s_tokens.iter();
90    
91    let mut out = Vec::new();
92
93    while let Some(next) = cmp_iter.next() {
94        match iter.next() {
95            Some(tt) => {
96                if tt != *next {
97                    cmp_iter = s_tokens.iter();
98                    if tt == s_tokens[0] {
99                        cmp_iter.next();
100                    }
101                }
102                out.push(tt);
103            }
104            None => return (out.into_iter().collect(), Found::No),
105        }
106    }
107
108    let found = if s_tokens.is_empty() { Found::No } else { Found::Yes };
109
110    out.truncate(out.len() - s_tokens.len());
111    (out.into_iter().collect(), found)
112}
113
114
115
116
117
118
119
120
121
122