【问题标题】:Rust macros - structs, enums, conversionRust 宏 - 结构、枚举、转换
【发布时间】:2023-01-03 05:26:41
【问题描述】:

有与(可能)rust 宏相关的问题,或者其他一些实现它的聪明方法。

  1. 以下代码来自第三方,无法修改
    pub struct Message0;
    
    pub struct Message1;
    
    pub struct Message {
       pub payload: Option<Payload>,
    }
    
    pub enum Payload {
       PayloadMessage0(Message0),
       PayloadMessage1(Message1),
    }
    
    pub fn third_party_send(msg: Message) {
       // ...
    }
    
    1. 希望以某种方式实现此功能(或不需要为每个 Message0 和 Message1 类型实现单独功能的其他变体)
    pub fn send<T>(specific_msg: T) {
        third_party_send(Message {
            payload: Some(Payload::PayloadMessage???(specific_msg)),
        });
    }
    

    我是生锈的新手,仍然对宏和泛型感到困惑....

【问题讨论】:

标签: rust


【解决方案1】:

我不认为你可以绕过必须为每个变体创建一个函数,但是你 可以为你创建一个宏。 然后我将它们包装在特征中以将 Message? 转换为 Payload 并启用您的通用功能:

pub trait ToPayload {
    fn to_payload(self) -> Payload;
}
macro_rules! to_payload {
    ($message:ident, $payload:ident) => {
        impl ToPayload for $message {
            fn to_payload(self) -> Payload {
                Payload::$payload(self)
            }
        }
    }
}

to_payload!{ Message0, PayloadMessage0 }
to_payload!{ Message1, PayloadMessage1 }

pub fn send<T: ToPayload>(specific_msg: T) {
    third_party_send(Message {
        payload: Some(specific_msg.to_payload())
    });
}

fn main() {
    send(Message0);
    send(Message1);
}

Playground

【讨论】:

  • 是的,这个会起作用。有趣的是,如果有一种方法可以在宏中采用一种类型 - Message0 并从中生成另一种类型 PayloadMessage0。我知道 proc-macro 会为此工作,但由于我无法修改第 3 方代码,proc-macro 在这种情况下没有用。
  • 当然你可以 - 只需实现From&lt;Message{1,0}&gt; for Payload(或者如果你不能因为孤儿规则而不能实现的另一个特征)并采用impl Into&lt;Payload&gt;
  • 我的意思是例如:($message:ident, $payload:ident) 如果可以只使用 $message:ident 并在宏中从它构建类似 Payload$message 的东西。所以最终结果将是 -to_payload!{ Message0 } 而不是 to_payload{ Message0, PayloadMessage0 }
猜你喜欢
  • 2021-01-04
  • 1970-01-01
  • 2021-01-04
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
  • 1970-01-01
相关资源
最近更新 更多