#枚举 #服务 #消息传递 #生成 #计数器 #服务代理 #返回值

nightly no-std ctrlgen

为消息传递服务生成枚举

7 个版本

0.3.2 2023 年 9 月 6 日
0.3.1 2022 年 11 月 25 日
0.2.4 2022 年 11 月 20 日
0.2.3 2022 年 10 月 21 日
0.2.1 2022 年 9 月 29 日

#1479 in Rust 模式

每月 21 次下载

MIT 许可证

21KB
383

ctrlgen-rs

vi/trait-enumizer 的分支,旨在更容易使用,但牺牲了一些灵活性。

即将提供文档。请参阅 trait-enumizer 的文档,并在此查看示例。

与 trait-enumizer 的区别

  • ctrlgen 只支持 inherent impls,它不会枚举 traits。
  • ctrlgen 优先生成 traits 的 impls 而不是 inherent 函数,以使用户更清楚地了解所做之事。例如,call 函数通过在枚举上实现 CallMut trait 来实现。
  • ctrlgen 尝试最小化和简化参数语法,但牺牲了一些可配置性。例如,call trait 总是会实现。
  • ctrlgen 需要nightly rust channel 以支持 GATs(以及其他功能)
  • ctrlgen 支持在结构定义中使用泛型(但在方法签名中不支持)
  • 代理的实现略有不同,通常更简单。然而,目前它不支持 trait-enumizer 有很多选项。
  • 目前尚未实现具有异步发送器的代理
  • 目前尚未实现异步返回值发送器。
  • no_std 支持尚未测试/实现,但将很容易完成。

这里的许多努力可能可以合并到 trait-enumizer 中,但我当时很着急,所以我还是实现了我需要的功能。

示例

struct Service<T: From<i32>> {
    counter: T,
}

#[ctrlgen::ctrlgen(
    pub enum ServiceMsg,
    trait ServiceProxy,
    returnval = TokioRetval,
)]
impl Service {
    pub fn increment_by(&mut self, arg: i32) -> i32 {
        self.counter = arg;
        self.counter
    }
}

这将生成类似于以下代码的内容

pub enum ServiceMsg
where TokioRetval: ::ctrlgen::Returnval,
{
    IncrementBy {
        arg: i32,
        ret: <TokioRetval as ::ctrlgen::Returnval>::Sender<i32>,
    },
}

impl ::ctrlgen::CallMut<Service> for ServiceMsg
where TokioRetval: ::ctrlgen::Returnval,
{
    type Output = core::result::Result<(), <TokioRetval as ::ctrlgen::Returnval>::SendError>;
    fn call_mut(self, this: &mut Service) -> Self::Output {
        match self {
            Self::IncrementBy { arg, ret } => {
                <TokioRetval as ::ctrlgen::Returnval>::send(ret, this.increment_by(arg))
            }
        }
    }
}

pub trait ServiceProxy: ::ctrlgen::Proxy<ServiceMsg>
{
    fn increment_by(&self, arg: i32) -> <TokioRetval as ::ctrlgen::Returnval>::RecvResult<i32> {
        let ret = <TokioRetval as ::ctrlgen::Returnval>::create();
        let msg = ServiceMsg::IncrementBy { arg, ret: ret.0 };
        ::ctrlgen::Proxy::send(self, msg);
        <TokioRetval as ::ctrlgen::Returnval>::recv(ret.1)
    }
}

impl<T: ::ctrlgen::Proxy<ServiceMsg>> ServiceProxy for T {}

返回值

通过设置 returnval = <Trait> 参数,您配置通过哪个通道发送返回值。<Trait> 必须实现 ctrlgen::Returnval

示例实现

pub struct FailedToSendRetVal;
pub struct TokioRetval;
impl Returnval for TokioRetval {
    type Sender<T> = promise::Sender<T>;
    type Receiver<T> = promise::Promise<T>;
    type SendError = FailedToSendRetVal;

    type RecvResult<T> = promise::Promise<T>;

    fn create<T>() -> (Self::Sender<T>, Self::Receiver<T>) {
        promise::Promise::channel()
    }

    fn recv<T>(rx: Self::Receiver<T>) -> Self::RecvResult<T> {
        rx
    }

    fn send<T>(tx: Self::Sender<T>, msg: T) -> core::result::Result<(), Self::SendError> {
        tx.send(msg).map_err(|_| FailedToSendRetVal)
    }
}

依赖项

~1.3–2.9MB
~60K SLoC