use quote::quote;
use syn::{parse_macro_input, LitStr};
#[proc_macro]
pub fn full_spec_id(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let proposed_id = parse_macro_input!(input as LitStr).value();
if is_valid_id(&proposed_id) {
quote!( FullSpecId::new_unchecked( #proposed_id )).into()
} else {
let message = format!(
"\"{proposed_id}\" is not a valid `FullSpecId`.\n\
`FullSpecId`s must begin with a letter or underscore, and contain only letters, numbers, or underscores."
);
quote! {
compile_error!(#message)
}
.into()
}
}
fn is_valid_id(proposed_id: &str) -> bool {
let mut chars = proposed_id.chars();
let first_char = chars.next();
let first_char_valid = first_char
.map(|c| c.is_ascii_alphabetic() || c == '_')
.unwrap_or(false);
let remainder_chars_valid =
chars.all(|c| c.is_ascii_alphabetic() || c == '_' || c.is_ascii_digit());
first_char_valid && remainder_chars_valid
}