Skip to main content

lumen_core/
output.rs

1//! Saying things without staking the process on being heard.
2//!
3//! `println!` and `eprintln!` panic when the write fails, which is the right
4//! call for a program whose output is the result and the wrong one for
5//! anything that has to keep running. A process whose output goes to a pipe
6//! nobody reads any more, or that a supervisor started with its streams
7//! closed, hits a broken pipe the next time it says anything; a server dies
8//! there, in the middle of answering somebody. A lost line of log is the
9//! smaller loss.
10//!
11//! So diagnostics go out through here: the line is written whenever anything
12//! is listening, and dropped when nothing is.
13
14use std::fmt::Arguments;
15use std::io::Write;
16
17/// Write a line to stdout, or drop it.
18pub fn to_stdout(message: Arguments<'_>) {
19    let _ = writeln!(std::io::stdout(), "{message}");
20}
21
22/// Write a line to stderr, or drop it.
23pub fn to_stderr(message: Arguments<'_>) {
24    let _ = writeln!(std::io::stderr(), "{message}");
25}
26
27/// Tell the person running this something. Reads like `println!`, and cannot
28/// end the process.
29#[macro_export]
30macro_rules! say_line {
31    ($($arg:tt)*) => { $crate::output::to_stdout(format_args!($($arg)*)) };
32}
33
34/// Warn the person running this about something. Reads like `eprintln!`, and
35/// cannot end the process.
36#[macro_export]
37macro_rules! warn_line {
38    ($($arg:tt)*) => { $crate::output::to_stderr(format_args!($($arg)*)) };
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    /// Whatever the write does, the caller carries on. A stream that is gone
46    /// cannot be arranged from inside the process that owns it, so the test
47    /// that serves through a closed pipe is the one that proves the rest.
48    #[test]
49    fn a_line_goes_out_without_the_caller_having_to_care() {
50        to_stdout(format_args!("lumen: {} {}", "a", 1));
51        to_stderr(format_args!("lumen: {} {}", "b", 2));
52        say_line!("lumen: {}", "said");
53        warn_line!("lumen: {}", "warned");
54    }
55}