impl Stream 无法取消固定

impl Stream cannot be unpinned

我正在尝试使用 crates_io_api 获取数据。 我试图从流中获取数据,但是 我无法让它工作。

AsyncClient::all_crates returns 一个 impl Stream。我如何从中获取数据?如果你提供代码会很有帮助。

我检查了 the async book 但它没有用。 谢谢。

这是我当前的代码。

use crates_io_api::{AsyncClient, Error};
use futures::stream::StreamExt;

async fn get_all(query: Option<String>) -> Result<crates_io_api::Crate, Error> {
  // Instantiate the client.
  let client = AsyncClient::new(
    "test (test@test.com)",
    std::time::Duration::from_millis(10000),
  )?;

  let stream = client.all_crates(query);

  // what should I do after?
  // ERROR: `impl Stream cannot be unpinned`
  while let Some(item) = stream.next().await {
      // ...
  }
}

这看起来像是 crates_io_api 一方的错误。获取 Streamnext 元素需要 StreamUnpin:

pub fn next(&mut self) -> Next<'_, Self> where
    Self: Unpin, 

因为Next存储了对Self的引用,所以必须保证Self在此过程中不被移动,否则有指针失效的风险。这就是 Unpin 标记特征所代表的。 crates_io_api 不提供此保证(尽管他们可以而且应该提供),因此您必须自己制作。要将 !Unpin 类型转换为 Unpin 类型,您可以将其固定到堆分配:

use futures::stream::StreamExt;

let stream = client.all_crates(query).boxed();

// boxed simply calls Box::pin
while let Some(elem) = stream.next() { ... }

或者您可以使用 pin_mut!/pin! 宏将其固定到堆栈:

let stream = client.all_crates(query);
futures::pin_mut!(stream);

while let Some(elem) = stream.next() { ... }

或者,您可以使用不需要 Unpin 的组合器,例如 for_each:

stream.for_each(|elem| ...)