如何在 Rust 中引用 impl 输出的类型?

发布于 2025-01-17 12:47:24 字数 800 浏览 2 评论 0 原文

我正在尝试实现Rust的流以在Tonic GRPC处理程序中使用,并遇到了以下困难:创建流的大多数方法都不容易表达类型,但是我需要实现的GRPC特征需要特定的流类型。这样的东西(简化):

// trait to implement
trait GrpcHandler {
  type RespStream: futures::Stream<ResponseType> + Send + 'static
  fn get_resp_stream() -> Self::RespStream;
}

// a start at implementing it
impl GrpcHandler for MyHandler {
  type RespStream = ???; // what do I put here?
  fn get_resp_stream() -> Self::RespStream {
    futures::stream::unfold((), |_| async {
      tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
      Some((ResponseType {}, ()))
    })
  }
}

我知道我的流的类型在技术上是类似的东西,例如 from&lt;(),复杂的fnsignaturewithimpl,complematedfuturesturesignaturewithimpl&gt; >对它是一种不透明的类型感到高兴。 如何参考此流的类型?

I'm trying to implement a stream in Rust for use in a tonic GRPC handler and encountered this difficulty: most ways of creating streams don't have easily-expressible types, yet the GRPC trait I need to implement requires a specific Stream type. Something like this (simplified):

// trait to implement
trait GrpcHandler {
  type RespStream: futures::Stream<ResponseType> + Send + 'static
  fn get_resp_stream() -> Self::RespStream;
}

// a start at implementing it
impl GrpcHandler for MyHandler {
  type RespStream = ???; // what do I put here?
  fn get_resp_stream() -> Self::RespStream {
    futures::stream::unfold((), |_| async {
      tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
      Some((ResponseType {}, ()))
    })
  }
}

I know the type of my stream is technically something like Unfold<(), ComplicatedFnSignatureWithImpl, ComplicatedFutureSignatureWithImpl>, but even if I typed that whole thing in, the compiler wouldn't be happy about it being an opaque type.
How can I refer to the type of this stream?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

仅此而已 2025-01-24 12:47:24

不幸的是,在稳定的 Rust 中没有好的方法可以在没有动态调度的情况下做到这一点。您必须使用dyn Stream,并且futures提供BoxStream

impl GrpcHandler for MyHandler {
    type RespStream = futures::stream::BoxStream<'static, ResponseType>;
    fn get_resp_stream() -> Self::RespStream {
        futures::stream::unfold((), |_| async {
            tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
            Some((ResponseType {}, ()))
        })
        .boxed()
    }
}

如果您使用 nightly,则可以使用不稳定的 type_alias_impl_trait 功能可以避免动态调度的开销:

#![feature(type_alias_impl_trait)]

impl GrpcHandler for MyHandler {
    type RespStream = impl futures::Stream<Item = ResponseType> + Send + 'static;
    fn get_resp_stream() -> Self::RespStream {
        futures::stream::unfold((), |_| async {
            tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
            Some((ResponseType {}, ()))
        })
    }
}

Unfortunately there is no good way in stable Rust to do that without dynamic dispatch. You have to use dyn Stream, and futures provides BoxStream for that:

impl GrpcHandler for MyHandler {
    type RespStream = futures::stream::BoxStream<'static, ResponseType>;
    fn get_resp_stream() -> Self::RespStream {
        futures::stream::unfold((), |_| async {
            tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
            Some((ResponseType {}, ()))
        })
        .boxed()
    }
}

If you use nightly, you can use the unstable type_alias_impl_trait feature to avoid the overhead of dynamic dispatch:

#![feature(type_alias_impl_trait)]

impl GrpcHandler for MyHandler {
    type RespStream = impl futures::Stream<Item = ResponseType> + Send + 'static;
    fn get_resp_stream() -> Self::RespStream {
        futures::stream::unfold((), |_| async {
            tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
            Some((ResponseType {}, ()))
        })
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文