Как устранить неоднозначность смешанной цепочки вызовов Iterator и Futures, не перемещая себя? - PullRequest
0 голосов
/ 20 мая 2018

Я пытаюсь добавить реализацию Futures Stream к существующей структуре, которая уже имеет синхронную реализацию Iterator.Чтобы сохранить код СУХИМ, я хочу изменить реализацию Iterator так, чтобы она вызывала новую реализацию Stream и ждала ее.

Я смоделировал мою реализацию Iterator после кодапример для Stream::by_ref:

stream.by_ref().take(2)

Моя реализация выглядит примерно так:

impl Iterator for Websocket {
    type Item = Message;

    fn next(&mut self) -> Option<Self::Item> {
        self.by_ref().take(1).wait().next().and_then(Result::ok)
    }
}

Однако я получаю ошибку с несколькими применимыми элементами:

error[E0034]: multiple applicable items in scope
   --> src/websocket/websocket.rs:330:14
    |
330 |         self.by_ref().take(1).wait().next().and_then(Result::ok)
    |              ^^^^^^ multiple `by_ref` found
    |
note: candidate #1 is defined in an impl of the trait `websocket::websocket::futures::Stream` for the type `websocket::websocket::Websocket`
   --> src/websocket/websocket.rs:149:1
    |
149 | impl Stream for Websocket {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `std::iter::Iterator` for the type `websocket::websocket::Websocket`
   --> src/websocket/websocket.rs:324:1
    |
324 | impl Iterator for Websocket {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #3 is defined in the trait `std::io::Write`
    = help: to disambiguate the method call, write `std::io::Write::by_ref(&mut self)` instead

Методы, которые я хотел вызвать слева направо:

Если я устраню неоднозначность кода, он будет выглядеть так:

impl Iterator for Websocket {
    type Item = Message;

    fn next(&mut self) -> Option<Self::Item> {
        <Self as Stream>::take(*<Self as Stream>::by_ref(self),1).wait().next().and_then(Result::ok)
    }
}

Однако тогда я получу пожизненную ошибку:

error[E0507]: cannot move out of borrowed content
   --> src/websocket/websocket.rs:331:32
    |
331 |         <Self as Stream>::take(*<Self as Stream>::by_ref(self),1).wait().next().and_then(Result::ok)
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content

Как мне сделать это однозначным, но оставить возможность вызывать take по результату by_ref?

Я знаю, что есть новая версия Futures, но я не могу использовать ее из-зас другими библиотеками, которые я использую, чтобы быть совместимым с APIверсия фьючерса, которую я использую.

1 Ответ

0 голосов
/ 20 мая 2018

Вы можете избежать выхода из заемного значения, не пытаясь выйти из заемного значения:

extern crate futures;

use futures::prelude::*;

struct Message;
struct Websocket;

impl Stream for Websocket {
    type Item = Message;
    type Error = ();

    fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
        Err(())
    }
}

impl Iterator for Websocket {
    type Item = Message;

    fn next(&mut self) -> Option<Self::Item> {
        let a = Stream::take(self, 1);
        let mut b = a.wait();
        let c = Iterator::next(&mut b);
        c.and_then(Result::ok)
    }
}

fn main() {}

Нет необходимости вызывать Stream::by_ref, поскольку начальный тип уже равен &mut Websocketпоэтому я удалил его.

При желании вы можете объединить их в одну строку:

fn next(&mut self) -> Option<Self::Item> {
    Stream::take(self, 1)
        .wait()
        .next()
        .and_then(Result::ok)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...