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 supports structured machine output (like JSON).
24 fn supports_structured_output() -> bool {
25 false
26 }
27
28 /// Is a schema of the output type available.
29
30 fn has_schema() -> bool {
31 false
32 }
33
34 fn try_print_schema(&mut self) -> Result<()> {
35 Err(Error::SchemaFailure("No schema defined".into()))
36 }
37
38 /// Returns true if the receiver was configured to output for machines.
39 fn is_machine(&self) -> bool;
40
41 /// Returns an error stream that errors can be written to.
42 fn stderr(&mut self) -> &mut dyn Write;
43
44 /// Writes the value to standard output without a newline.
45 ///
46 /// This is a no-op if `is_machine` returns true.
47 fn print(&mut self, value: impl std::fmt::Display) -> Result<()> {
48 if !self.is_machine() {
49 write!(self, "{value}")?;
50 }
51 Ok(())
52 }
53
54 /// Writes the value to standard output with a newline.
55 ///
56 /// This is a no-op if `is_machine` returns true.
57 fn line(&mut self, value: impl std::fmt::Display) -> Result<()> {
58 if !self.is_machine() {
59 writeln!(self, "{value}")?;
60 }
61 Ok(())
62 }
63
64 /// Displays the item in whatever formatted style is most appropriate based
65 /// on is_machine and the underlying implementation
66 fn item(&mut self, value: &Self::OutputItem) -> Result<()>
67 where
68 Self::OutputItem: Display;
69}