为什么我必须明确macro_use
宏不是我的代码直接使用的,而是仅由我的代码依赖项使用?
下面有两种情况说明:
call
,do_parse
,map
,take
,error_if
parse_der_defined
(函数),fold_parsers
(函数),DerObject
(结构),DerObjectContent
(结构)奖金问题
编码时处理此问题的最佳工作流程是什么?只是编译错误,添加名称,冲洗,重复?
// Why is this necessary? My code does not directly use macros from this scope.
#[macro_use(call, do_parse, map, take)]
extern crate nom;
// Why is this necessary? My code does not directly use macros from this scope.
#[macro_use(error_if)]
extern crate rusticata_macros;
// Why is this necessary? My code does not directly use macros from this scope.
#[macro_use(parse_der_sequence_defined, parse_der_defined, fold_parsers)]
extern crate der_parser;
// My code does not directly use these names. Why do I need to `use` them?
use der_parser::{der_read_element_header, DerObjectContent};
// Why is this necessary? My code does not directly use these names.
use nom::{Err, ErrorKind};
// I actually use these
use nom::IResult;
use der_parser::DerObject;
fn seq_of_integers(input: &[u8]) -> IResult<&[u8], DerObject> {
parse_der_sequence_defined!(input, der_parser::parse_der_integer)
}
fn main() {
let input = [
0x30, // ASN.1 sequence
0x03, // length 3 bytes
0x02, // ASN.1 Integer
0x01, // length 1 byte
0x07, // 7
];
let der_result = seq_of_integers(&input);
match der_result {
IResult::Done(_unparsed_suffix, der) => {
assert_eq!(_unparsed_suffix.len(), 0);
let der_objects = der.as_sequence().unwrap();
for (index, der_object) in der_objects.iter().enumerate() {
println!("{}: {}", index, der_object.content.as_u32().unwrap());
}
}
IResult::Error(error) => {
eprintln!("{}", error);
}
IResult::Incomplete(_needed) => {
eprintln!("{:?}", _needed);
}
};
}
答案 0 :(得分:3)
宏是卫生的,但他们不会带来&#34;来自其定义范围的事物。
如果在一个包中定义宏,并使用相对名称而不是绝对名称(如果宏使用der_read_element_name
而不是::der_parser::der_read_element_name
生成代码),则需要使用{{1将这些方法纳入范围。
解决方法是在定义宏时始终使用绝对名称,或者使用&#39;他们在宏观范围内。例如,如果您有一个打开文件的宏,则执行以下两项操作之一。导入:
use
或直接使用绝对路径:
macro_rules! open {
($file:expr) => ({
// note: this has to be inside the macro expansion
// `::std` means this works anywhere, not just in
// the crate root where `std` is in scope.
use ::std::fs::File;
File::open($file)
})
}
使用其他宏的宏发生了类似的事情!如果你有两个板条箱,比如说macro_rules! open {
($file:expr) => ({
::std:fs::File::open($file)
})
}
:
cratea
和macro_rules! say_hello {
() => (println!("hi"))
}
:
crateb
然后当有人将#[macro_use]
extern crate cratea;
macro_rules! conversation {
() => ({
say_hello!();
println!("goodbye");
})
}
与crateb
一起使用时,它实际上会扩展为conversation!()
,如果目标条件箱中不存在say_hello!(); println!("goodbye");
,则会出错。
解决方法是将所有宏从say_hello
重新导出到cratea
。您可以使用以下方法执行此操作:
crateb
这意味着依赖于extern crate cratea;
pub use cratea::*;
使用#[macro_use]
的任何人都可以访问所有crateb
的宏。因此,当cratea
中的宏展开以引用crateb
中的宏时,它将起作用。
关于工作流程,个人轶事:
我发现cratea
与cargo-watch成为我所知道的最佳工作流程。我将在终端中启动cargo check
,每当保存文件时,它都会启动检查并报告语法错误。
一旦我感到非常自信并且没有错误,我实际上会根据项目运行cargo watch
和/或cargo run
。