如何通过期货:: Sink发送物品清单?

时间:2017-01-23 16:30:16

标签: rust future

我有一个要通过期货发送的项目列表:: scenario 'currently used transport mode cannot be re-selected' do expect(page).to have_css("h2.summary", text: "Single event") # do it in one query page.click_link("Change journey") # click_link will find the content anyway so no need to check for it before expect(page).to have_css('#travel-times-preview') # By default Capybara only finds visible elements so checking visibility is pointeless, if you've changed that default see #4 end

Sink

我可以使用

发送一个数据包
let mut list = VecDeque::new();
/* add a bunch of Packet items to list */
let (sink, stream) = tcp_stream.framed(PacketCodec).split();

如何发送整个列表?

1 个答案:

答案 0 :(得分:10)

使用新软件时,我发现在深入潜水之前阅读文档非常有用。一般而言,Rust社区提供了非常好的资源。

例如,Tokio项目的entire site of documentation包含selection of working examplesgenerated API documentation for Sink在这里也很有价值。

我建议所有程序员学会做的另一件事是创建MCVE问题。这使他们能够专注于问题的核心,同时也消除了问题背后的瑕疵和磨练。这是一个案例:

use futures; // 0.1.26

fn thing<S>(sink: S)
where
    S: futures::Sink<SinkItem = i32>,
{
    let mut all_the_things = vec![1, 2, 3, 4, 5];

    while let Some(v) = all_the_things.pop() {
        sink.send(v);
    }
}

我们收到错误消息

error[E0382]: use of moved value: `sink`
  --> src/lib.rs:10:9
   |
3  | fn thing<S>(sink: S)
   |          -  ---- move occurs because `sink` has type `S`, which does not implement the `Copy` trait
   |          |
   |          consider adding a `Copy` constraint to this type argument
...
10 |         sink.send(v);
   |         ^^^^ value moved here, in previous iteration of loop

让我们回到API文档...

fn send(self, item: Self::SinkItem) -> Send<Self>
where
    Self: Sized, 

由此,我们可以看到send使用接收器并返回Send值。这很奇怪,不是吗?一旦你看到Send实现了Future,它实际上并不是 奇怪 - 如果流已满,可能会阻止流进入流中。这是背压的概念。结果为Future是您如何知道项目何时实际添加到流中的方法。 Future Send的实施具有Item = SSink的具体类型。因此,一个解决方案是推动未来完成以获得接收器,而一种方式就是调用wait

use futures::Future; // 0.1.26
use std::fmt;

fn thing<S>(mut sink: S)
where
    S: futures::Sink<SinkItem = i32>,
    S::SinkError: fmt::Debug,
{
    let mut all_the_things = vec![1, 2, 3, 4, 5];

    while let Some(v) = all_the_things.pop() {
        let f = sink.send(v);
        sink = f.wait().expect("Something bad happened while sending");
    }
}

这编译,但并不是非常漂亮。回到文档,我们还可以看到Sink::send_all,它需要Stream。我们可以使用stream::iter_ok

从迭代器创建Stream
use futures::Future; // 0.1.26
use std::fmt;

fn thing<S>(sink: S)
where
    S: futures::Sink<SinkItem = i32>,
    S::SinkError: fmt::Debug,
{
    let all_the_things = vec![1, 2, 3, 4, 5];

    sink.send_all(futures::stream::iter_ok(all_the_things))
        .wait()
        .expect("Something bad happened while sending");
}

同样,我们使用wait来推动未来的完成。如果我们忘记了,那就是一个很好的错误:&#34;除非进行了调查,否则期货什么也不做&#34;。但是,wait并不是处理此问题的正确方法。通常,您希望将Future返回给调用者,因为他们想知道什么时候已经把所有东西都塞进了接收器。