在Rust中实现一个C2C构建器模式

wnrlj8wa  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(101)

我想为构建器实现一个future。这可能是常见的示例,例如通过构建器配置请求,然后发送它。
我想为一个构建器实现IntoFuture,但是如果没有动态分派,我就做不到。我的直觉告诉我,我应该能够做到这一点,而不必分配额外的内存。
例如

#[derive(Default)]
struct FooFluentBuilder {
    value: i32,
}

impl FooFluentBuilder {
    fn value(mut self, value: i32) -> Self {
        self.value = value;
        self
    }

    async fn send(self) -> Result<i32, &'static str> {
        tokio::time::sleep(Duration::from_millis(50)).await;
        Ok(self.value)
    }
}

impl std::future::IntoFuture for FooFluentBuilder {
    type Output = Result<i32, &'static str>;
    type IntoFuture = std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output>>>;

    fn into_future(self) -> Self::IntoFuture {
        Box::pin(self.send())
    }
}

#[tokio::main]
async fn main() {
    let _response = FooFluentBuilder::default().value(5).send().await;
    let _response = FooFluentBuilder::default().value(5).await;
}

字符串
在这个例子中,我将我的Foo请求转换成一个由Pin<Box<dyn Future<Output = ...>>>表示的动态未来。理想情况下,我希望FooFluentBuilder::send返回的类型,但Future类型是不透明的,不能通过Rust表示。
目前,是否有现有的机制可以在不使用动态分派的情况下实现IntoFuture
看上面的例子。我使用了一个dyn Future,但是我想要一个具体的未来。我不知道如何实现它。

s4chpxco

s4chpxco1#

你可以为你创建的一个类型手动实现Future,然后用<Self as IntoFuture>::IntoFuture命名这个类型。

use std::future::{Future, IntoFuture};
use std::pin::Pin;
use std::task::{Context, Poll};

#[derive(Default)]
struct FooFluentBuilder {
    value: i32,
}

impl FooFluentBuilder {
    fn value(mut self, value: i32) -> Self {
        self.value = value;
        self
    }

    fn send(self) -> SendFut {
        SendFut { builder: self }
    }
}

struct SendFut {
    builder: FooFluentBuilder
}

impl Future for SendFut {
    type Output = Result<i32, &'static str>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        Poll::Ready(Ok(self.get_mut().builder.value)) 
    }
}

impl IntoFuture for FooFluentBuilder {
    type Output = <<Self as IntoFuture>::IntoFuture as IntoFuture>::Output;
    type IntoFuture = SendFut;

    fn into_future(self) -> Self::IntoFuture {
        self.send()
    }
}

#[tokio::main]
async fn main() {
    let _response = FooFluentBuilder::default().value(5).send().await;
    let _response = FooFluentBuilder::default().value(5).await;
}

字符串

相关问题