#[cfg(not(kernel))]
use proc_macro2 as proc_macro;
use proc_macro::{TokenStream, TokenTree};
pub(crate) struct Generics {
pub(crate) decl_generics: Vec<TokenTree>,
pub(crate) impl_generics: Vec<TokenTree>,
pub(crate) ty_generics: Vec<TokenTree>,
}
pub(crate) fn parse_generics(input: TokenStream) -> (Generics, Vec<TokenTree>) {
let mut decl_generics = vec![];
let mut impl_generics = vec![];
let mut ty_generics = vec![];
let mut rest = vec![];
let mut nesting = 0;
let mut toks = input.into_iter();
let mut at_start = true;
let mut skip_until_comma = false;
while let Some(tt) = toks.next() {
if nesting == 1 && matches!(&tt, TokenTree::Punct(p) if p.as_char() == '>') {
break;
} else if nesting >= 1 {
decl_generics.push(tt.clone());
}
match tt.clone() {
TokenTree::Punct(p) if p.as_char() == '<' => {
if nesting >= 1 && !skip_until_comma {
impl_generics.push(tt);
}
nesting += 1;
}
TokenTree::Punct(p) if p.as_char() == '>' => {
if nesting == 0 {
break;
} else {
nesting -= 1;
if nesting >= 1 && !skip_until_comma {
impl_generics.push(tt);
}
}
}
TokenTree::Punct(p) if skip_until_comma && p.as_char() == ',' => {
if nesting == 1 {
impl_generics.push(tt.clone());
impl_generics.push(tt);
skip_until_comma = false;
}
}
_ if !skip_until_comma => {
match nesting {
0 => rest.push(tt),
1 => {
match tt.clone() {
TokenTree::Ident(i) if at_start && i.to_string() == "const" => {
let Some(name) = toks.next() else {
break;
};
impl_generics.push(tt);
impl_generics.push(name.clone());
ty_generics.push(name.clone());
decl_generics.push(name);
at_start = false;
}
TokenTree::Ident(_) if at_start => {
impl_generics.push(tt.clone());
ty_generics.push(tt);
at_start = false;
}
TokenTree::Punct(p) if p.as_char() == ',' => {
impl_generics.push(tt.clone());
ty_generics.push(tt);
at_start = true;
}
TokenTree::Punct(p) if p.as_char() == '\'' && at_start => {
impl_generics.push(tt.clone());
ty_generics.push(tt);
}
TokenTree::Punct(p) if p.as_char() == '=' => {
skip_until_comma = true;
}
_ => impl_generics.push(tt),
}
}
_ => impl_generics.push(tt),
}
}
_ => {}
}
}
rest.extend(toks);
(
Generics {
impl_generics,
decl_generics,
ty_generics,
},
rest,
)
}