Как мне интерпретировать подпись read_until и что такое AsyncRead + BufRead в Tokio? - PullRequest
1 голос
/ 01 июня 2019

Я пытаюсь понять асинхронный ввод-вывод в Rust. Следующий код основан на фрагменте из Катарины Фей Январь 2019, разговор , который работает для меня:

use futures::future::Future;
use std::io::BufReader;
use tokio::io::*;

fn main() {
    let reader = BufReader::new(tokio::io::stdin());
    let buffer = Vec::new();

    println!("Type something:");
    let fut = tokio::io::read_until(reader, b'\n', buffer)
        .and_then(move |(stdin, buffer)| {
            tokio::io::stdout()
                .write_all(&buffer)
                .map_err(|e| panic!(e))
        })
        .map_err(|e| panic!(e));

    tokio::run(fut);
}

Прежде чем найти этот код, я попытался выяснить его из документации read_until.

Как мне интерпретировать подпись read_until, чтобы использовать ее в примере кода, подобном приведенному выше?

pub fn read_until<A>(a: A, byte: u8, buf: Vec<u8>) -> ReadUntil<A> 
where
    A: AsyncRead + BufRead, 

В частности, как я могу узнать из чтения документации, какие параметры передаются в замыкание and_then и ожидаемый результат?

1 Ответ

2 голосов
/ 01 июня 2019

Параметры для and_then

К сожалению, стандартная схема документации Rust делает фьючерсы довольно сложными для отслеживания.

Начиная с read_until документации, которую вы связалиЯ вижу, что он возвращает ReadUntil<A>.Я нажму на это, чтобы перейти к ReadUntil документации .

Это возвращаемое значение описывается как:

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

Я ожидаю, что он реализует черту Future - и я вижу, что это так.Я также предположил бы, что Item, к которому решает будущее, является неким вектором, но я не знаю точно, что именно, поэтому я продолжаю копать:

  1. Сначала я посмотрю в разделе "Реализации черты""и найти impl<A> Future for ReadUntil<A>
  2. Я нажимаю [+] расширитель

Наконец я вижу связанный type Item = (A, Vec<u8>).Это означает, что Future будет возвращать пару значений: A, так что он, вероятно, возвращает мне исходный reader, который я передал, плюс вектор байтов.

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

fn and_then<F, B>(self, f: F) -> AndThen<Self, B, F>
where
    F: FnOnce(Self::Item) -> B,
    B: IntoFuture<Error = Self::Error>,
    Self: Sized,

Функция and_then задокументирована как принимающая два параметра, но self неявно передаетсякомпилятор при использовании точечного синтаксиса для chain функций, который говорит нам, что мы можем написать read_until(A, '\n', buffer).and_then(...).Второй параметр в документации, f: F, становится первым аргументом, переданным в and_then в нашем коде.

Я вижу, что f является замыканием, потому что тип F показан как FnOnce(Self::Item) -> B (который, если я щелкаю по ссылкам на главу Закрытие книги Rust .

Переданное закрытие f, принимает Self::Item в качестве параметра. Я только что узнал, чтоItem равно (A, Vec<u8>), поэтому я ожидаю написать что-то вроде .and_then(|(reader, buffer)| { /* ... /* })

AsyncRead + BufRead

Это накладывает ограничения на то, из какого типа читателя можно читатьСозданный BufReader реализует BufRead.

Полезно, что Tokio предоставляет реализацию AsyncRead для BufReader, поэтомунам не нужно беспокоиться об этом, мы можем просто пойти дальше и использовать BufReader.

...