是否可以判断某个字段是某个类型还是在过程宏中实现某个方法?

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

我创建了一个实现特征的过程宏,但是为了使它能够工作,我需要为每个字段获取原始字节。问题是如何根据字段类型获取字段的字节。

是否有某种方法可以测试字段上是否存在函数,以及它是否未尝试其他函数?

例如。这样的事情:

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 rust-proc-macros
1个回答
2
投票

是否可以判断某个字段是某个类型还是在过程宏中实现某个方法?

不它不是。

宏在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做了同样的事情,有多种方法可以与二进制数据进行序列化:

© www.soinside.com 2019 - 2024. All rights reserved.