我希望 Rust 在编译时处理这个字符串。我该怎么办?

问题描述 投票:0回答:1

我使用

include_str!()
从文件中导入 str,我想将其传递到 proc_marco,bug 它不起作用。我从 rustc 收到错误
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()
}

但是它返回的是原始文本,没有任何处理。

rust rust-cargo compile-time cargo rust-proc-macros
1个回答
0
投票

Ass eqqyal 指出,默认情况下宏是从外向内求值的,但是当某些表达式将产生文字时,就像在您的情况下一样,您可以使用 unstable

TokenStream::expand_expr
:

反转它

your_macros/src/lib.rs
的顶部:

#![feature(proc_macro_expand)]

在带有

LitStr
的定义中插入以下内容:

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();
    // …
© www.soinside.com 2019 - 2024. All rights reserved.