![](/img/trans.png)
[英]How to pass a format! string and format! arguments to a Rust macro that creates a function?
[英]pass macro arguments to other macro
我是 rust 的新手。 我正在嘗試創建一個宏,它需要一個緩沖區,然后從中解碼一些數據並創建變量的給定列表。 如果發生錯誤,那么它應該打印錯誤並繼續,因為我將在接收緩沖區的循環中調用它。 像這樣的東西: -
for bin_ref in bufs {
extract!( bin_ref anime &str episodes u32 season u32);
//if everything goes ok then do some cool stuff with
//above variables otherwise take next buf_ref
}
我怎樣才能做到這一點? 因此,我采用了這種方法:-
#[macro_export]
macro_rules! extract {
( $buf:ident $($var:ident $typ:ty),* ) => {
$(
ext_type!( $buf $var $typ );
)*
};
}
#[macro_export]
macro_rules! ext_type {
( $buf:ident $var:ident &str ) => {
let mut $var : &str = ""; //some string specific function
println!("doing cool things with '{}' which is string ",$var);
};
( $buf:ident $var:ident u32 ) => {
let mut $var : u32 = 34; //some u32 specific function
println!("doing cool things with '{}' which is u32",$var);
}
}
我有以下測試 function:-
fn macro_test() {
let mut bin_ref : &[u8] = &[0u8;100];
ext_type!(bin_ref anime &str); // works
ext_type!(bin_ref episodes u32 ); // works
extract!( bin_ref username &str, password &str ); // does not work. why ??
}
當我編譯這個時,我得到以下錯誤: -
error: no rules expected the token `&str`
--> src/easycode.rs:11:34
|
11 | ext_type!( $buf $var $typ );
| ^^^^ no rules expected this token in macro call
...
19 | macro_rules! ext_type {
| --------------------- when calling this macro
...
48 | extract!( bin_ref username &str, password &str );
| ------------------------------------------------- in this macro invocation
為什么我不能只將$typ
傳遞給ext_type!
宏? 從代碼調用時它可以工作
ext_type!
宏的規則最后需要文字標記&str
和u32
。 這些文字標記無法匹配extract!
中的匹配片段$typ:ty
! . 為了成功地將文字標記與匹配的片段匹配, 它必須是tt
、 ident
或lifetime
。
在這種情況下,唯一可行的選項是tt
,簡單地說,就是一個解析器令牌。 但是,一種類型通常由多個標記組成; 以&str
,它由兩個標記&
和str
組成。 因此,我們必須使用重復來完全捕獲具有tt
s 的類型: $($typ:tt)+
會做得很好。
然而,對tt
使用無限重復是有代價的——一個tt
將匹配幾乎所有內容,所以簡單地將$typ:ty
替換為$($typ:tt)+
是行不通的,因為$typ
重復將捕獲所有內容,直到在宏調用結束時,為了防止這種情況發生,我們必須在宏規則匹配器中划定類型標記樹,以阻止它消耗所有內容。 以使調用稍微冗長為代價,將括號中的重復括起來將為我們提供很好的服務,並停止與我們想要的完全匹配的令牌樹。 修改后的宏如下所示:
#[macro_export]
macro_rules! extract {
( $buf:ident $($var:ident ($($typ:tt)+)),* ) => {
$(
ext_type!( $buf $var $($typ)+);
)*
};
}
注意匹配器中的$typ:ty
替換為($($typ:tt)+)
(這是一個用括號括起來的標記樹重復),以及轉錄器中的$typ
替換為$($typ)+
.
宏規則調用如下:
extract!(bin_ref username (&str), password (&str), id (u32));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.