Разрешить кортежу на будущее - PullRequest
0 голосов
/ 18 октября 2018

В ржавчине я пытаюсь построить будущее, извлекая два бита данных из запроса .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 ...

Я почти уверен, что это потому, что два члена кортежа - это фьючерсы, и с ними можно иметь дело, но кортеж - нет, но я не уверен, как определить значения фьючерсов ипоместите их в кортеж.

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Ваша проблема сводится к:

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)`

Кстати, IntoFuture реализовано для Result:

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

А для кортежа :

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

детская площадка с вашим примером: он работает, но он достаточно запутан, чтобы получить результаты.Смотрите также комментарии ниже.

0 голосов
/ 18 октября 2018

Первым элементом вашего кортежа является будущее, а вторым элементом является 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))
    });

Полный пример кода на игровой площадке

Если вам все еще не удается заставить код работать, я предлагаю опубликовать вопрос, включающий минимальный пример реального кода, который вы пытаетесь скомпилировать, а также фактическое сообщение об ошибке, которое вы получаете,Сообщения об ошибках для кода, использующего будущие комбинаторы, могут быть длинными и запутанными, но они по-прежнему являются наиболее важной информацией, чтобы понять, почему код не компилируется.

...