与tokio和std :: future :: Future

时间:2019-04-24 07:05:29

标签: asynchronous rust stdio rust-tokio

问题:

我想从当前进程的STDIN中异步读取,转换读取的数据,然后将其泵送到子进程(使用std::process::Command::new创建)。我尝试这样做,如下所示:

fn transform_input(buff: &[u8]) -> Vec<u8> {
    unimplemented!()
}

async fn read_stdin<'a>(
    child_stdin: &'a mut ChildStdin,
    buff: &'a mut [u8],
) -> Result<bool, std::io::Error> {
    // async read from parent stdin
    let (_, bff, sz) = await!(tokio::io::read(tokio::io::stdin(), buff));
    // transform data
    let transformed = transform_input(bff);
    // pump to stdin of child process
    match child_stdin.write_all(bff) {
        // if # bytes read from parent input < 1, EOF/closed input stream
        Ok(()) => Ok(sz < 1),
        Err(e) => Err(e),
    }
}

无法编译:

error[E0277]: the trait bound `tokio_io::io::read::Read<tokio::io::Stdin, &mut [u8]>: std::future::Future` is not satisfied
  --> src/main.rs:25:24
   |
25 |     let (_, bff, sz) = await!(tokio::io::read(tokio::io::stdin(), buff));
   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `tokio_io::io::read::Read<tokio::io::Stdin, &mut [u8]>`
   |
   = note: required by `std::future::poll_with_tls_waker`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

如何成功从STDIN异步读取?

上下文

该程序的目的是包装任意外部CLI工具,将控制通道注入stdin,以使elixir代码更好地控制外部程序,并将stderr和stdout分成两个不同的流(按照瓷器/ erlexec的样式)。我看不到需要多个OS级别的线程-该程序将花费大部分时间等待来自stdin的输入或子进程的stdout / stderr的输出,在接收到数据时执行廉价且快速的操作。这是所需的控制流程:

  1. 如果stdin上的数据准备就绪:读取数据,剥离控制通道,转发给子stdin
  2. 如果子stdout上的数据准备就绪:读取数据,添加频道标识符,转发给父stdout
  3. 如果子stderr上的数据准备就绪:读取数据,添加通道标识符,转发给父stdout

我认为由epoll之类的东西支持的单线程循环比开始新线程要好得多,并且我知道tokio stdin依赖这种机制。但是,要获得可靠的异步锈蚀和Tokio使用指南似乎非常困难,许多人指出该地区变化如此之快,以至于那些指南很快就过时了。过去,我只编写了一些防锈程序,所以知道我很可能会错过一些基本知识并感谢您的帮助。令我感到羞耻的是,我什至不清楚编译错误消息的含义-看起来东京期货和标准期货不兼容,但我认为应该是这样。

0 个答案:

没有答案