use proc_macro::TokenStream;
use quote::quote;
use rxml_validation::{validate_name, validate_ncname};
use syn::{
parse::{Parse, ParseStream},
*,
};
struct Input {
data: LitStr,
ty_mod: Path,
}
impl Parse for Input {
fn parse(input: ParseStream) -> Result<Self> {
let data = input.parse()?;
input.parse::<Token![,]>()?;
let ty_mod = input.parse()?;
if input.peek(Token![,]) {
input.parse::<Token![,]>()?;
}
Ok(Self { data, ty_mod })
}
}
#[proc_macro]
pub fn xml_name(input: TokenStream) -> TokenStream {
let Input { data, ty_mod } = parse_macro_input!(input);
let s = data.value();
let tokens = match validate_name(&s) {
Ok(()) => quote! { core::mem::transmute::<_, &#ty_mod::NameStr>(#s) },
Err(e) => {
let err = format!("invalid Name string {:?}: {}", s, e);
quote! { compile_error!(#err) }
}
};
tokens.into()
}
#[proc_macro]
pub fn xml_ncname(input: TokenStream) -> TokenStream {
let Input { data, ty_mod } = parse_macro_input!(input);
let s = data.value();
let tokens = match validate_ncname(&s) {
Ok(()) => quote! { core::mem::transmute::<_, &#ty_mod::NcNameStr>(#s) },
Err(e) => {
let err = format!("invalid NCName string {:?}: {}", s, e);
quote! { compile_error!(#err) }
}
};
tokens.into()
}