writer/
writer.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::io::{stderr, stdout, Write};
6
7use crate::TestBuffers;
8
9/// An object that can be used to produce output, with no support for outputting
10/// structured machine-interpretable output.
11pub struct Writer {
12    stdout: Box<dyn Write>,
13    stderr: Box<dyn Write>,
14}
15
16impl Writer {
17    /// Create a new writer that doesn't support machine output at all, with the
18    /// given streams underlying it.
19    pub fn new_buffers<'a, O, E>(stdout: O, stderr: E) -> Self
20    where
21        O: Write + 'static,
22        E: Write + 'static,
23    {
24        let stdout = Box::new(stdout);
25        let stderr = Box::new(stderr);
26        Self { stdout, stderr }
27    }
28
29    /// Create a new Writer that doesn't support machine output at all
30    pub fn new() -> Self {
31        Self::new_buffers(Box::new(stdout()), Box::new(stderr()))
32    }
33
34    /// Returns a writer backed by string buffers that can be extracted after
35    /// the writer is done with
36    pub fn new_test(test_writer: &TestBuffers) -> Self {
37        Self::new_buffers(test_writer.stdout.clone(), test_writer.stderr.clone())
38    }
39
40    pub fn stderr(&mut self) -> &'_ mut Box<dyn Write> {
41        &mut self.stderr
42    }
43}
44
45impl Write for Writer {
46    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
47        self.stdout.write(buf)
48    }
49
50    fn flush(&mut self) -> std::io::Result<()> {
51        self.stdout.flush()
52    }
53}
54
55#[cfg(test)]
56mod test {
57    use super::*;
58
59    #[test]
60    fn writer_implements_write() {
61        let test_buffers = TestBuffers::default();
62        let mut writer = Writer::new_test(&test_buffers);
63        writer.write_all(b"foobar").unwrap();
64
65        let (stdout, stderr) = test_buffers.into_strings();
66        assert_eq!(stdout, "foobar");
67        assert_eq!(stderr, "");
68    }
69
70    #[test]
71    fn writing_errors_goes_to_the_right_stream() {
72        let test_buffers = TestBuffers::default();
73        let mut writer = Writer::new_test(&test_buffers);
74        writeln!(writer.stderr(), "hello").unwrap();
75
76        let (stdout, stderr) = test_buffers.into_strings();
77        assert_eq!(stdout, "");
78        assert_eq!(stderr, "hello\n");
79    }
80}