use crate::*;
pub(crate) fn parse_ident_segment(input: ParseStream) -> syn::Result<String> {
let token_tree: proc_macro2::TokenTree = input.parse()?;
match token_tree {
proc_macro2::TokenTree::Ident(ident) => {
let raw_name: String = ident.to_string();
Ok(raw_name
.strip_prefix(RAW_IDENT_PREFIX)
.unwrap_or(&raw_name)
.to_string())
}
_ => Err(input.error(ERR_EXPECTED_IDENTIFIER)),
}
}
pub(crate) fn parse_kebab_name(input: ParseStream) -> syn::Result<String> {
if input.peek(LitStr) {
let lit: LitStr = input.parse()?;
return Ok(lit.value());
}
let mut name: String = String::new();
while input.peek(Token![-]) {
input.parse::<Token![-]>()?;
name.push(CHAR_HYPHEN);
}
if !input.is_empty() && !input.peek(Token![:]) {
let first_segment: String = parse_ident_segment(input)?;
name.push_str(&first_segment);
}
while input.peek(Token![-]) {
input.parse::<Token![-]>()?;
name.push(CHAR_HYPHEN);
let next_segment: String = parse_ident_segment(input)?;
name.push_str(&next_segment);
}
Ok(name)
}
pub(crate) fn reconstruct_kebab_from_tokens(tokens: &proc_macro2::TokenStream) -> String {
let iter: Peekable<proc_macro2::token_stream::IntoIter> = tokens.clone().into_iter().peekable();
let mut result: String = String::new();
for token in iter {
match token {
proc_macro2::TokenTree::Ident(ident) => {
let raw_name: String = ident.to_string();
let clean_name: String = raw_name
.strip_prefix(RAW_IDENT_PREFIX)
.unwrap_or(&raw_name)
.to_string();
result.push_str(&clean_name);
}
proc_macro2::TokenTree::Punct(punct) if punct.as_char() == CHAR_HYPHEN => {
result.push(CHAR_HYPHEN);
}
proc_macro2::TokenTree::Group(group) => {
let inner: String = reconstruct_kebab_from_tokens(&group.stream());
result.push_str(&inner);
}
proc_macro2::TokenTree::Literal(literal) => {
let literal_token_stream: proc_macro2::TokenStream =
proc_macro2::TokenTree::Literal(literal).into();
if let Ok(literal_string) = syn::parse2::<LitStr>(literal_token_stream) {
result.push_str(&literal_string.value());
}
}
_ => {}
}
}
result
}