2017-01-23 81 views
1

我有一個項目列表,通過期貨:: Sink派:如何通過期貨發送物品清單:: Sink?

let mut list = VecDeque::new(); 
/* add a bunch of Packet items to list */ 
let (sink, stream) = tcp_stream.framed(PacketCodec).split(); 

我可以給使用

if let Some(first) = list.pop_front() { 
    sink.send(first); 
} 

如何發送整個列表中的一個包?

+2

*「以下顯然不起作用*」 - 怎麼樣?你可以包括錯誤,或描述你看到的行爲? –

+2

在提出有關堆棧溢出的問題時,請生成一個[MCVE]。 – Shepmaster

+1

我敢打賭,**缺少的錯誤信息**說了一些關於*期待'T',找到了'&T' *。如果是這樣的話,我強烈建議你回頭閱讀[* The Rust Programming Language *](https://doc.rust-lang.org/stable/book/),因爲這不會是關於Tokio的問題,而是Rust的基本所有權。 – Shepmaster

回答

7

當使用一個新的軟件時,我發現在潛入太深之前閱讀文檔非常有用。一般來說,Rust社區提供了相當不錯的資源。

例如,除了selection of working examples之外,Tokio項目還有一個entire page talking about Streams and Sinksgenerated API documentation for Sink也是非常寶貴的。

我推薦所有新程序員學會做的另一件事是創建一個MCVE的問題。這使他們能夠專注於問題的核心,同時還能夠消除問題背後的言辭和磨礪。這裏有一個這種情況:

extern crate futures; 

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); 
    } 
} 

fn main() {} 

我們得到錯誤信息

error[E0382]: use of moved value: `sink` 
--> src/main.rs:9:9 
    | 
9 |   sink.send(v); 
    |   ^^^^ value moved here in previous iteration of loop 
    | 
    = note: move occurs because `sink` has type `S`, which does not implement the `Copy` trait 

讓我們回頭API文檔...

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

從這一點,我們可以看到,send消耗接收器並返回一個Send對象。這很奇怪,不是嗎!實際上並不奇怪,一旦你看到Send實現Future - 將某些內容推入流中可能會阻塞流是否已滿;這是背壓的概念。結果爲Future是您如何知道該項目何時實際添加到流中。 Future的執行SendItem = SSink的具體類型。因此一個解決方案是推動未來完成獲得匯回來,這樣做的一個方法是調用wait

use std::fmt; 
use futures::Future; 

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創建一個迭代器Stream

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]; 
    let wrapped = all_the_things.into_iter().map(Result::Ok); 

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

我們再次使用wait帶動未來完成。如果我們忘記了一個很好的錯誤:「期貨什麼也不做,除非被調查」。但是,wait並不是真正處理此問題的正確方法。通常,您想要將Future返回給調用者,因爲他們想要知道什麼時候所有東西都被推入水槽。

+2

很好的答案! https://tokio.rs也是一個夢幻般的指針。它肯定需要在谷歌中排名靠前。我一直在使用源代碼和文檔以及一些博客來找出tokio。 –

+0

我相信Google的排名會穩步攀升; Tokio 0.1僅在2周前發佈! – Shepmaster

+0

感謝您的詳細解答。它爲我點了點東西,說明爲什麼你會故意設計一個API來利用Rust的移動語義。 –