2 个版本

0.1.1 2019年9月23日
0.1.0 2019年9月20日

#323 in 命令行界面

Download history 924/week @ 2024-03-14 881/week @ 2024-03-21 905/week @ 2024-03-28 777/week @ 2024-04-04 620/week @ 2024-04-11 659/week @ 2024-04-18 927/week @ 2024-04-25 973/week @ 2024-05-02 1829/week @ 2024-05-09 1307/week @ 2024-05-16 1054/week @ 2024-05-23 883/week @ 2024-05-30 563/week @ 2024-06-06 745/week @ 2024-06-13 606/week @ 2024-06-20 441/week @ 2024-06-27

2,430 每月下载
用于 16 个crate(12个直接使用)

MIT 许可证

9KB

平静I/O

在Rust中向标准输出和错误流写入很容易:使用其中一个 print!println! (stdout)、eprint!eprintln! (stderr) 宏来格式化消息并将其直接打印到适当的文件描述符。

但是,这些宏返回 (),而不是一个 io::Result,即使它们执行I/O。这是因为如果写入失败,它们会触发panic。通常,这是可以的:标准流基本上总是存在的。

这里有一个它们不存在的例子

prints_more_than_ten_lines | head

Unix的 head 程序从其标准输入读取十行(默认情况下),将其打印到其标准输出,然后退出。当它退出时,它会关闭其标准流。

head 退出时,它关闭管道的读取端。当内核处理管道读取端的 close() 调用,它会向持有管道写入端的过程发送 SIGPIPE 信号(C运行时 crt0 会捕获并终止,但Rust运行时会忽略),然后任何未来的对管道的 write() 调用都会立即返回 -EPIPE

Rust的 std::io::Write 函数正确地将此转换为 Err,然后 println! 解包它,开始panic。

在面临关闭的流时,平静的I/O存储库不会恐慌:它传播错误,并允许调用者优雅地展开并退出。

此存储库公开了四个宏:stdout!stdoutln!stderr!stderrln!。这些宏的行为与上面列出的宏完全一样,只是它们返回从 write!writeln!io::Result,而不是展开它并可能引发恐慌。

此外,此存储库导出了一个函数属性,pipefail,它仅抑制 BrokenPipe 错误。它可以附加到任何返回 io::Result 的函数(但应仅附加到 main)。带有 #[pipefail] 的函数其主体周围包裹了一个 match 隔板,它将 Ok(_)Err(io::ErrorKind::BrokenPipe) 都替换为 Ok(()),并保留所有其他错误不变。

use calm_io::*;

#[pipefail]
fn main() -> std::io::Result<()> {
    stdoutln!("Hello stdout from Rust")?;
    stderrln!("Hello stderr from Rust")?;
}

作为一个例子,考虑这个对 yes | head 的重新实现

//  examples/yeah.rs
use calm_io::*;

#[pipefail]
fn main () -> std::io::Result<!> {
    let text = std::env::args().nth(1).unwrap_or("y".to_string());
    loop {
        stdoutln!("{}", text)?;
    }
}

在您的shell中尝试运行这些命令!

$ cargo run --example good_yes | head > /dev/null
$ echo "${PIPESTATUS[@]}"
# The name is `PIPESTATUS` in bash, but `pipestatus` (lowercase!) in zsh
0 0
# yeah exits successfully, head exits successfully
$ yes | head > /dev/null
$ echo "${PIPESTATUS[@]}"
141 0
# yes crashes due to SIGPIPE, head exits successfully
$ cargo run --example bad_yes | head > /dev/null
thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', src/libstd/io/stdio.rs:792:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

将来,可能会添加其他抑制属性,或者创建一个可以接受要抑制的错误列表的通用抑制属性。

依赖项

~1.5MB
~35K SLoC