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}