我使用
include_str!()
从文件中导入字符串并将其传递到 proc_marco 中,但它不起作用。我收到 expected string literal
错误。这是我的代码:
macro_rules! ptcl_layer {
() => {
include_str!("tcp_to_msg.layer")
};
}
pub static TEMPLETE: &'static str = ptcl_layer!();
pub static TEMPLETE_HEADER: &'static str = get_protocol_layer_header!(ptcl_layer!());
pub static TEMPLETE_END: &'static str = get_protocol_layer_end!(ptcl_layer!());
#[proc_macro]
pub fn get_protocol_layer_header(_s: TokenStream) -> TokenStream {
let total_str = parse_macro_input!(_s as LitStr).value();
let header = total_str.lines().next().unwrap();
let header = header.replace("${.LEN}\n", "");
let output = quote::quote! {
#header
};
TokenStream::from(output)
}
#[proc_macro]
pub fn get_protocol_layer_end(_s: TokenStream) -> TokenStream {
let input = parse_macro_input!(_s as LitStr);
let input = input.value();
let last_line = input.lines().last().unwrap_or("");
let output = quote::quote! {
#last_line
};
TokenStream::from(output)
}
完整的错误消息:
error: expected string literal
--> src/controller/mod.rs:16:71
|
16 | pub static TEMPLETE_HEADER: &'static str = get_protocol_layer_header!(ptcl_layer!());
| ^^^^^^^^^^
*.layer 如下:
<? lines: ${.LEN}
${.CONTENT}
<? end
我还尝试了另一个版本的代码:
#[proc_macro]
pub fn get_protocol_layer_header(_s: TokenStream) -> TokenStream {
let total_str = _s.to_string();
let header = total_str.lines().next().unwrap();
let header = header.replace("${.LEN}\n", "");
header.parse().unwrap()
}
#[proc_macro]
pub fn get_protocol_layer_end(_s: TokenStream) -> TokenStream {
let total_str = _s.to_string();
let last_line = total_str.lines().last().unwrap_or("");
last_line.parse().unwrap()
}
但是它返回的是原始文本,没有任何处理。
正如 eqqyal 所指出的,默认情况下宏是从外向内求值的,但是当某些表达式将产生文字时,就像在您的情况下一样,您可以使用 unstable
TokenStream::expand_expr
: 反转它
在
your_macros/src/lib.rs
的顶部:
#![feature(proc_macro_expand)]
在带有
LitStr
的定义中插入以下内容:
#[proc_macro]
pub fn get_protocol_layer_header(input: TokenStream) -> TokenStream {
let input = input.expand_expr().unwrap();
let total_str = parse_macro_input!(input as LitStr).value();
// …
这是您想要使用的最外层宏必须接受的内容,因此如果您无法更改
get_protocol_layer_header
和类似的定义,或者无法使用 nightly,您必须解决它并插入相应的字符串文字build.rs
脚本。