Rust 在'BoxStream'上使用流组合器
在使用该库时,我遇到了这样一种情况:一个流在返回给用户之前需要通过不确定数量的其他流进行映射。由于在这个操作结束时输出流的确切类型是未知的,所以在将流存储在结构中和返回它时,我一直在使用trait对象 尽管这种方法工作得很好,但它有一个不幸的副作用,即导致内部Rust 在'BoxStream'上使用流组合器,rust,future,Rust,Future,在使用该库时,我遇到了这样一种情况:一个流在返回给用户之前需要通过不确定数量的其他流进行映射。由于在这个操作结束时输出流的确切类型是未知的,所以在将流存储在结构中和返回它时,我一直在使用trait对象 尽管这种方法工作得很好,但它有一个不幸的副作用,即导致内部流对象大小不定。这是一个问题,因为每个人的签名都需要Self:Sized,这意味着我甚至不能对返回的BoxStream等待(),以便将其转换为阻塞迭代器 下面是一个可能导致此问题的情况示例: struct Server { rece
流
对象大小不定。这是一个问题,因为每个人的签名都需要Self:Sized
,这意味着我甚至不能对返回的BoxStream
等待(),以便将其转换为阻塞迭代器
下面是一个可能导致此问题的情况示例:
struct Server {
receiver: Option<Box<Stream<Item = usize, Error = ()> + Send>>,
}
impl Server {
pub fn new() -> Server {
let (tx, rx) = channel(0);
// do things with the tx (subscribe to tcp socket, connect to database, etc.)
Server { receiver: Some(rx.boxed()) }
}
/// Maps the inner `Receiver` through another stream, essentially duplicating it.
pub fn get_stream(&mut self) -> Result<Box<Stream<Item = usize, Error = ()> + Send>, ()> {
let (tx, rx) = channel(0);
let strm = self.receiver.take().unwrap();
let mut tx_opt = Some(tx);
let new_strm = strm.map(move |msg| {
// unfortunate workaround needed since `send()` takes `self`
let mut tx = tx_opt.take().unwrap();
tx = tx.send(msg.clone()).wait().unwrap();
tx_opt = Some(tx);
msg
});
simbroker.receiver = Some(new_strm.boxed());
Ok(rx.boxed())
}
}
pub fn main() {
let server = Server::new();
// possible that this may happen 0..n times
let rx: BoxStream<usize, ()> = server.get_stream();
// can't do this since the inner `Stream` trait object isn't `Sized` and `wait()`
// (along with all other stream combinators) requires that in their signatures.
for msg in rx.wait() {
// compiler error here
// ...
}
}
struct服务器{
接收人:选择权,
}
impl服务器{
pub fn new()->Server{
let(tx,rx)=信道(0);
//使用tx执行操作(订阅tcp套接字、连接到数据库等)
服务器{receiver:Some(rx.boxed())}
}
///通过另一个流映射内部“Receiver”,实质上是复制它。
pub fn get_stream(&mut self)->结果{
let(tx,rx)=信道(0);
设strm=self.receiver.take().unwrap();
让mut tx_opt=Some(tx);
让new|strm=strm.map(move | msg |{
//由于'send()'需要'self,因此需要一种不幸的解决方法`
让mut tx=tx_opt.take().unwrap();
tx=tx.send(msg.clone()).wait().unwrap();
tx_opt=一些(tx);
味精
});
simbroker.receiver=Some(new_strm.boxed());
Ok(rx.boxed())
}
}
pub fn main(){
让server=server::new();
//可能发生0..n次
让rx:BoxStream=server.get_stream();
//无法执行此操作,因为内部'Stream'trait对象不是'size'和'wait()`
//(以及所有其他流组合器)要求在其签名中使用。
对于rx.wait()中的msg{
//这里有编译器错误
// ...
}
}
如上面的代码所示,BoxStream
s是必需的,因为在流上调用map()
会将其类型从Receiver
更改为map
,这将使其无法存储回结构中。返回的BoxStream
几乎不可能执行任何操作,因为它的大小是。事实上,trait objectStream
s唯一可用的函数是poll()
,它应该永远不会在任务之外调用
有没有什么方法可以避免这个问题,而不必返回包含可能发生的任何一种流的枚举?编写我自己的结构来实现流
会以某种方式解决这个问题吗?正如@FrancisGagné在评论中指出的那样,futures rs
在futures::Stream
模块中声明impl Stream for Box
。在测试我的代码时,我未能导入流
,因此该特征不在范围内
编译器没有因为缺少wait()
函数而触发错误,因为它首先遇到了未大小的问题
通过添加use futures::Stream代码>到函数的开头。我无法重现您的问题(在修复无关问题后)。在未来的rs中有impl-Stream-for-Box
,这应该可以让它正常工作。确保你的问题包含一个错误消息和你收到的错误消息;在这个特定的测试中,我没有做使用futures::Stream
;rustc遇到了未指定大小的错误,因为impl
作为wait()
存在于Stream
模块中,因此编译在注意到wait()
不在范围内之前就出错了。非常感谢@FrancisGagné!如果你想把它变成一个答案,我会接受它的解决;如果不是的话,我会自己做的。