cli_engine/output/
renderer.rs1use std::{io::Write, str::FromStr};
2
3use crate::{CliCoreError, DetailedError, Result};
4
5use super::{
6 Envelope, build_detailed_error_envelope, build_error_envelope, render_human, render_json,
7 render_toon,
8};
9
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub enum OutputFormat {
13 Toon,
15 Json,
17 Human,
19}
20
21impl FromStr for OutputFormat {
22 type Err = CliCoreError;
23
24 fn from_str(value: &str) -> std::result::Result<Self, Self::Err> {
25 if value == "human" {
26 Ok(Self::Human)
27 } else if value == "toon" {
28 Ok(Self::Toon)
29 } else {
30 Ok(Self::Json)
31 }
32 }
33}
34
35#[must_use]
37pub fn is_valid_output_format(format: &str) -> bool {
38 matches!(format, "toon" | "json" | "human")
39}
40
41#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
43pub struct RendererFactory;
44
45impl RendererFactory {
46 #[must_use]
48 pub fn new() -> Self {
49 Self
50 }
51
52 pub fn render(&self, format: &str, envelope: &Envelope) -> Result<String> {
54 render_format(format, envelope)
55 }
56
57 pub fn write(&self, mut writer: impl Write, format: &str, envelope: &Envelope) -> Result<()> {
59 writer
60 .write_all(self.render(format, envelope)?.as_bytes())
61 .map_err(CliCoreError::from)
62 }
63}
64
65pub fn render(format: OutputFormat, envelope: &Envelope) -> Result<String> {
67 match format {
68 OutputFormat::Human => {
69 envelope.serialization_result()?;
70 Ok(render_human(envelope))
71 }
72 OutputFormat::Json => render_json(envelope),
73 OutputFormat::Toon => render_toon(envelope),
74 }
75}
76
77pub fn render_format(format: &str, envelope: &Envelope) -> Result<String> {
79 render(format.parse()?, envelope)
80}
81
82pub fn write_render(mut writer: impl Write, format: &str, envelope: &Envelope) -> Result<()> {
84 writer
85 .write_all(render_format(format, envelope)?.as_bytes())
86 .map_err(CliCoreError::from)
87}
88
89pub fn render_data(
91 format: OutputFormat,
92 data: impl serde::Serialize,
93 system: impl Into<String>,
94) -> Result<String> {
95 let data = serde_json::to_value(data)?;
96 render(format, &Envelope::success(data, system))
97}
98
99pub fn render_data_format(
101 format: &str,
102 data: impl serde::Serialize,
103 system: impl Into<String>,
104) -> Result<String> {
105 let data = serde_json::to_value(data)?;
106 render_format(format, &Envelope::success(data, system))
107}
108
109pub fn render_error(
111 format: OutputFormat,
112 err: &(dyn std::error::Error + 'static),
113 system: &str,
114) -> Result<String> {
115 render(format, &build_error_envelope(err, system))
116}
117
118pub fn render_error_format(
120 format: &str,
121 err: &(dyn std::error::Error + 'static),
122 system: &str,
123) -> Result<String> {
124 render_format(format, &build_error_envelope(err, system))
125}
126
127pub fn render_detailed_error(
129 format: OutputFormat,
130 err: &dyn DetailedError,
131 system: &str,
132) -> Result<String> {
133 render(format, &build_detailed_error_envelope(err, system))
134}
135
136pub fn render_detailed_error_format(
138 format: &str,
139 err: &dyn DetailedError,
140 system: &str,
141) -> Result<String> {
142 render_format(format, &build_detailed_error_envelope(err, system))
143}