extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::Expr;
use syn::parse::Parse;
use syn::parse_macro_input;
use syn::{Error, Ident, Token, parse::ParseStream};
#[cfg(any(feature = "def_cn"))]
fn get_def_lang() -> Box<str> {
Box::from("cn")
}
#[cfg(any(feature = "def_en"))]
fn get_def_lang() -> Box<str> {
Box::from("en")
}
struct Args {
cn: Expr,
en: Expr,
}
#[proc_macro]
pub fn lang_tr(input: TokenStream) -> TokenStream {
let args = parse_macro_input!(input as Args);
let cn = &args.cn;
let en = &args.en;
let result = match get_def_lang().as_ref() {
"cn" => quote! { #cn },
"en" => quote! { #en },
_ => panic!("必须且只能启用一项默认语言"),
};
TokenStream::from(result)
}
impl Parse for Args {
fn parse(input: ParseStream) -> syn::Result<Self> {
let mut cn = None;
let mut en = None;
while !input.is_empty() {
let key = input.parse::<Ident>()?;
input.parse::<Token![=]>()?;
let expr = input.parse::<Expr>()?;
match key.to_string().as_str() {
"cn" => {
if cn.is_some() {
return Err(Error::new_spanned(key, "Duplicate 'cn' key"));
}
cn = Some(expr);
}
"en" => {
if en.is_some() {
return Err(Error::new_spanned(key, "Duplicate 'en' key"));
}
en = Some(expr);
}
_ => return Err(Error::new_spanned(key, "Expected key 'cn' or 'en'")),
}
if input.peek(Token![,]) {
input.parse::<Token![,]>()?;
} else {
break;
}
}
Ok(Args {
cn: cn.ok_or_else(|| panic!("中文:cn值获取失败,缺少必要参数")).unwrap(),
en: en
.ok_or_else(|| panic!("English: en value retrieval failed, missing necessary parameters"))
.unwrap(),
})
}
}