Skip to main content

proc_tools_helper/
lib.rs

1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::Expr;
6use syn::parse::Parse;
7use syn::parse_macro_input;
8use syn::{Error, Ident, Token, parse::ParseStream};
9
10#[cfg(any(feature = "def_cn"))]
11fn get_def_lang() -> Box<str> {
12    Box::from("cn")
13}
14#[cfg(any(feature = "def_en"))]
15fn get_def_lang() -> Box<str> {
16    Box::from("en")
17}
18
19// 解析参数结构体
20struct Args {
21    cn: Expr,
22    en: Expr,
23}
24
25/// 多语言字符串翻译宏实现
26/// - 根据设置的默认语言选择对应的中英文字符串。
27/// - 这是一个过程宏,用于在编译时根据语言设置选择不同的字符串常量。
28///
29/// # 参数
30/// - `input`: 宏输入的TokenStream,包含中英文字符串配置
31///
32/// # 返回值
33/// - `TokenStream`: 根据默认语言选择的字符串对应的TokenStream
34///
35/// # 错误类型
36/// - 如果未设置默认语言或设置了多个默认语言,会触发panic
37/// - 如果输入参数不符合语法要求,会在编译时报错
38///
39/// # 示例
40/// ```
41/// use proc_tools_helper::lang_tr;
42///
43/// let message = lang_tr!(cn = "你好世界", en = "Hello World");
44/// // 根据设置语言,message 会是 "你好世界" 或 "Hello World"
45/// ```
46#[proc_macro]
47pub fn lang_tr(input: TokenStream) -> TokenStream {
48    let args = parse_macro_input!(input as Args);
49    let cn = &args.cn;
50    let en = &args.en;
51
52    let result = match get_def_lang().as_ref() {
53        "cn" => quote! { #cn },
54        "en" => quote! { #en },
55        _ => panic!("必须且只能启用一项默认语言"),
56    };
57
58    TokenStream::from(result)
59}
60
61impl Parse for Args {
62    fn parse(input: ParseStream) -> syn::Result<Self> {
63        let mut cn = None;
64        let mut en = None;
65
66        // 解析所有键值对(支持任意顺序,逗号分隔)
67        while !input.is_empty() {
68            let key = input.parse::<Ident>()?;
69            input.parse::<Token![=]>()?;
70            let expr = input.parse::<Expr>()?;
71
72            match key.to_string().as_str() {
73                "cn" => {
74                    if cn.is_some() {
75                        return Err(Error::new_spanned(key, "Duplicate 'cn' key"));
76                    }
77                    cn = Some(expr);
78                }
79                "en" => {
80                    if en.is_some() {
81                        return Err(Error::new_spanned(key, "Duplicate 'en' key"));
82                    }
83                    en = Some(expr);
84                }
85                _ => return Err(Error::new_spanned(key, "Expected key 'cn' or 'en'")),
86            }
87
88            // 如果还有逗号,继续解析下一个
89            if input.peek(Token![,]) {
90                input.parse::<Token![,]>()?;
91            } else {
92                break;
93            }
94        }
95
96        // 确保两个键都存在(否则报错)
97        Ok(Args {
98            cn: cn.ok_or_else(|| panic!("中文:cn值获取失败,缺少必要参数")).unwrap(),
99            en: en
100                .ok_or_else(|| panic!("English: en value retrieval failed, missing necessary parameters"))
101                .unwrap(),
102        })
103    }
104}