writer/
tool_io.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::fmt::Display;
6use std::io::Write;
7
8use crate::{Error, Result};
9
10/// ToolIO defines the necessary functions to perform output from a tool,
11/// potentially including type-safe machine output if required.
12///
13/// There are three provided implementations:
14// [`crate::MachineWriter`] and [`crate::VerifiedMachineWriter`],
15/// and [`crate::SimpleWriter`]. These provide either type-safe,
16/// type-safe with schema, or string-only output respectively.
17pub trait ToolIO: Write + Sized {
18    /// The type of object that is expected for the [`Self::item`] call (or
19    /// any machine output writing functions that may be added by an
20    /// implementation)
21    type OutputItem;
22
23    /// Whether this can theoretically support machine output given the right configuration.
24    fn is_machine_supported() -> bool;
25
26    /// Is a schema of the output type available.
27    fn has_schema() -> bool {
28        false
29    }
30
31    fn try_print_schema(&mut self) -> Result<()> {
32        Err(Error::SchemaFailure("No schema defined".into()))
33    }
34
35    /// Returns true if the receiver was configured to output for machines.
36    fn is_machine(&self) -> bool;
37
38    /// Returns an error stream that errors can be written to.
39    fn stderr(&mut self) -> &'_ mut Box<dyn Write>;
40
41    /// Writes the value to standard output without a newline.
42    ///
43    /// This is a no-op if `is_machine` returns true.
44    fn print(&mut self, value: impl std::fmt::Display) -> Result<()> {
45        if !self.is_machine() {
46            write!(self, "{value}")?;
47        }
48        Ok(())
49    }
50
51    /// Writes the value to standard output with a newline.
52    ///
53    /// This is a no-op if `is_machine` returns true.
54    fn line(&mut self, value: impl std::fmt::Display) -> Result<()> {
55        if !self.is_machine() {
56            writeln!(self, "{value}")?;
57        }
58        Ok(())
59    }
60
61    /// Displays the item in whatever formatted style is most appropriate based
62    /// on is_machine and the underlying implementation
63    fn item(&mut self, value: &Self::OutputItem) -> Result<()>
64    where
65        Self::OutputItem: Display;
66}