解决未来的元组

时间:2018-10-18 03:10:41

标签: rust tuples hyper

在生锈中,我试图通过使用超级客户端作为元组从.get请求中提取两位数据来实现未来。问题在于生成的类型不能正常工作。

因此,给出一些这样的代码:

let result = client
  .get(url)
  .map_err(|err| Error::from(err))
  .and_then(|response| {
    (response
      .into_body()
      .concat2()
      .map(|body| String::from_utf8(body.to_vec()).unwrap())
      .map_err(|err| Error::from(err)),
    response
      .headers()
      .get(CONTENT_TYPE)
      .map(|content_type| content_type.to_str()))
  });

我遇到类似the trait "futures::IntoFuture" is not implemented for ...

的错误

我非常确定这是因为tuple的两个成员都是期货并且可以处理,但是tuple不是,但是我不确定如何解析期货的价值并将其放入交易中。元组。

2 个答案:

答案 0 :(得分:0)

元组的第一个元素是未来,但是第二个元素是Option。只要所有元素都实现IntoFuture并为元组实现并且错误类型匹配,您就只能解决一个问题,因此有一个更简单的解决方案。

另一个问题是response.into_body()消耗了response,因此您以后无法访问它来检索标头。由于我们只有一个未来需要解决,因此最简单的解决方案是先从响应中提取内容类型,然后将其附加到map()方法的结果中:

let result = client
    .get("https://www.stackoverflow.com/".parse().unwrap())
    .map_err(|err| Error::from(err))
    .and_then(|response| {
        let content_type = response
            .headers()
            .get(CONTENT_TYPE)
            .map(|content_type| content_type.to_str().unwrap().to_string());
        response
            .into_body()
            .concat2()
            .map(|body| (
                String::from_utf8(body.to_vec()).unwrap(),
                content_type,
            ))
            .map_err(|err| Error::from(err))
    });

Full example code in the playground

如果您仍然无法使代码正常工作,建议您提出一个问题,其中包括您尝试编译的实际代码的最小示例以及收到的实际错误消息。使用未来的组合器的代码错误消息可能会变得冗长而混乱,但它们仍然是了解为什么代码无法编译的最重要的信息。

答案 1 :(得分:0)

您的问题归结为:

use futures::*;

struct Foo {}

impl Future for Foo {
    type Item = u32;
    type Error = u32;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        Ok(Async::Ready(100))
    }
}

fn main() {
    let f = Foo {};

    let _result = f
        .and_then(|val| {
            (val * 2, val * 4)
        });
}

给出:

   |                                    
18 |  .and_then(|val| {
   |   ^^^^^^^^ the trait `futures::future::IntoFuture` is not implemented for `(u32, u32)`

通过为Result实现IntoFuture的方式:

impl<T, E> IntoFuture for Result<T, E>

对于the tuple

impl<A, B> IntoFuture for (A, B) 
where
    A: IntoFuture,
    B: IntoFuture<Error = A::Error>,

返回一个结果元组有效:

use futures::*;

struct Foo {}

impl Future for Foo {
    type Item = u32;
    type Error = u32;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        Ok(Async::Ready(100))
    }
}

fn main() {
    let f = Foo {};

    let _result = f
        .and_then(|val| {
            (Ok(val * 2), Ok(val * 4))
        });
}

playground以您的示例为例:它可以工作,但是要获得结果却很费劲。另请参见下面的评论。