use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::parse::{Parse, ParseStream};
pub(crate) struct IdentifierConstructor {
src_crate: syn::Path,
str: syn::LitStr,
}
impl IdentifierConstructor {
pub(crate) fn validate_and_expand_str_conversion<F, T, E>(
&self,
id_type: &str,
validate_fn: F,
) -> TokenStream
where
F: FnOnce(&str) -> Result<T, E>,
{
let (id_type, is_ref) = if let Some(id_type) = id_type.strip_prefix('&') {
(id_type, true)
} else {
(id_type, false)
};
assert!(validate_fn(&self.str.value()).is_ok(), "Invalid {id_type}");
let src_crate = &self.src_crate;
let str = &self.str;
let ampersand = is_ref.then(|| quote! { & });
let ident = syn::Ident::new(id_type, Span::call_site());
quote! {
<#ampersand #src_crate::#ident as ::std::convert::TryFrom<&str>>::try_from(#str).unwrap()
}
}
}
impl Parse for IdentifierConstructor {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let src_crate = input.parse()?;
let _: syn::Token![,] = input.parse()?;
let str = input.parse()?;
Ok(Self { src_crate, str })
}
}