将宏参数传递给其他宏
pass macro arguments to other macro
我是生锈新手。我正在尝试创建宏,它接受一个缓冲区,然后从中解码一些数据并创建 givens 变量列表。如果发生错误,那么它应该打印错误并继续,因为我将在接收缓冲区的循环中调用它。像这样:-
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);
}
}
我有以下测试功能:-
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
。为了成功地将文字标记匹配到匹配的片段,it must be a tt
, ident
or lifetime
.
在这种情况下唯一可行的选项是 tt
,简单地说,它只是一个解析器标记。但是,一种类型通常由多个标记组成;以 &str
为例,它由两个标记 &
和 str
组成。因此,我们必须使用重复来完全捕获具有 tt
s 的类型:$($typ:tt)+
会做得很好。
使用 tt
的无限重复是有代价的,但是 - tt
将匹配几乎所有内容,因此简单地将 $typ:ty
替换为 $($typ:tt)+
不会工作,因为 $typ
重复将捕获所有内容,直到宏调用结束!为了防止这种情况发生,我们必须 delimit 宏规则匹配器中的类型标记树以阻止它消耗所有内容。以使调用稍微冗长为代价,将重复包含在括号中将对我们很有帮助,并停止令牌树与我们想要的位置完全匹配。修改后的宏如下所示:
#[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));
我是生锈新手。我正在尝试创建宏,它接受一个缓冲区,然后从中解码一些数据并创建 givens 变量列表。如果发生错误,那么它应该打印错误并继续,因为我将在接收缓冲区的循环中调用它。像这样:-
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);
}
}
我有以下测试功能:-
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
。为了成功地将文字标记匹配到匹配的片段,it must be a tt
, ident
or lifetime
.
在这种情况下唯一可行的选项是 tt
,简单地说,它只是一个解析器标记。但是,一种类型通常由多个标记组成;以 &str
为例,它由两个标记 &
和 str
组成。因此,我们必须使用重复来完全捕获具有 tt
s 的类型:$($typ:tt)+
会做得很好。
使用 tt
的无限重复是有代价的,但是 - tt
将匹配几乎所有内容,因此简单地将 $typ:ty
替换为 $($typ:tt)+
不会工作,因为 $typ
重复将捕获所有内容,直到宏调用结束!为了防止这种情况发生,我们必须 delimit 宏规则匹配器中的类型标记树以阻止它消耗所有内容。以使调用稍微冗长为代价,将重复包含在括号中将对我们很有帮助,并停止令牌树与我们想要的位置完全匹配。修改后的宏如下所示:
#[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));