我创建了一个实现特征的过程宏,但是为了使它能够工作,我需要为每个字段获取原始字节。问题是如何根据字段类型获取字段的字节。
是否有某种方法可以测试字段上是否存在函数,以及它是否未尝试其他函数?
例如。这样的事情:
if item.field::function_exist {
//do code
} else {
//do other code
}
目前我正在寻找创建另一个trait / member函数,我只需要为所有基元创建,并为更大的字段(如结构)创建一个过程宏。例如:
if item.field::as_bytes().exists {
(&self.#index).as_bytes()
} else {
let bytes = (&self.#index).to_bytes();
&bytes
}
有一个字符串,它有一个as_bytes
成员函数,而i32
没有。这意味着当结构的成员字段不是字符串时,我需要额外的代码。我可能需要一个match
而不是if
,但if
就足够了这个例子。
是否可以判断某个字段是某个类型还是在过程宏中实现某个方法?
不它不是。
宏在Rust代码的abstract syntax tree (AST)上运行。这意味着您基本上只需获取用户输入的字符。
如果用户代码有像type Foo = Option<Result<i32, MyError>>
这样的东西,并且你处理了一些使用Foo
的代码,宏就不会知道它“真的”是一个Option
。
即使它确实知道类型,知道可用的方法会更难。未来的板条箱可以创建将方法添加到现有类型的特征。在程序宏运行的时间点,这些包可能还没有被编译。
我正在寻找创建另一个trait / member函数,我只需要为所有基元创建,并为更大的字段(如结构)创建一个过程宏。
这是正确的解决方案。如果你看一下任何现有的常用程序宏,那就是它的作用。这允许编译器执行编译器要执行的操作。
这对于可维护性来说也更好 - 现在这些原始实现存在于标准的Rust文件中,而不是嵌入在宏内部。更容易阅读和调试。
你的箱子会有这样的东西:
// No real design put into this trait
trait ToBytes {
fn encode(&self, buf: &mut Vec<u8>);
}
impl ToBytes for str {
fn encode(&self, buf: &mut Vec<u8>) {
buf.extend(self.as_bytes())
}
}
// Other base implementations
并且您的过程宏将以直接的方式实现:
#[derive(ToBytes)]]
struct Foo {
a: A,
b: B,
}
变
impl ToBytes for Foo {
fn encode(&self, buf: &mut Vec<u8>) {
ToBytes::encode(&self.a);
ToBytes::encode(&self.b);
}
}
作为一个具体的例子,Serde做了同样的事情,有多种方法可以与二进制数据进行序列化: