use std::{io::Write, str::FromStr};
use crate::{CliCoreError, DetailedError, Result};
use super::{
Envelope, build_detailed_error_envelope, build_error_envelope, render_human, render_json,
render_toon,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum OutputFormat {
Toon,
Json,
Human,
}
impl FromStr for OutputFormat {
type Err = CliCoreError;
fn from_str(value: &str) -> std::result::Result<Self, Self::Err> {
if value == "human" {
Ok(Self::Human)
} else if value == "toon" {
Ok(Self::Toon)
} else {
Ok(Self::Json)
}
}
}
#[must_use]
pub fn is_valid_output_format(format: &str) -> bool {
matches!(format, "toon" | "json" | "human")
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct RendererFactory;
impl RendererFactory {
#[must_use]
pub fn new() -> Self {
Self
}
pub fn render(&self, format: &str, envelope: &Envelope) -> Result<String> {
render_format(format, envelope)
}
pub fn write(&self, mut writer: impl Write, format: &str, envelope: &Envelope) -> Result<()> {
writer
.write_all(self.render(format, envelope)?.as_bytes())
.map_err(CliCoreError::from)
}
}
pub fn render(format: OutputFormat, envelope: &Envelope) -> Result<String> {
match format {
OutputFormat::Human => {
envelope.serialization_result()?;
Ok(render_human(envelope))
}
OutputFormat::Json => render_json(envelope),
OutputFormat::Toon => render_toon(envelope),
}
}
pub fn render_format(format: &str, envelope: &Envelope) -> Result<String> {
render(format.parse()?, envelope)
}
pub fn write_render(mut writer: impl Write, format: &str, envelope: &Envelope) -> Result<()> {
writer
.write_all(render_format(format, envelope)?.as_bytes())
.map_err(CliCoreError::from)
}
pub fn render_data(
format: OutputFormat,
data: impl serde::Serialize,
system: impl Into<String>,
) -> Result<String> {
let data = serde_json::to_value(data)?;
render(format, &Envelope::success(data, system))
}
pub fn render_data_format(
format: &str,
data: impl serde::Serialize,
system: impl Into<String>,
) -> Result<String> {
let data = serde_json::to_value(data)?;
render_format(format, &Envelope::success(data, system))
}
pub fn render_error(
format: OutputFormat,
err: &(dyn std::error::Error + 'static),
system: &str,
) -> Result<String> {
render(format, &build_error_envelope(err, system))
}
pub fn render_error_format(
format: &str,
err: &(dyn std::error::Error + 'static),
system: &str,
) -> Result<String> {
render_format(format, &build_error_envelope(err, system))
}
pub fn render_detailed_error(
format: OutputFormat,
err: &dyn DetailedError,
system: &str,
) -> Result<String> {
render(format, &build_detailed_error_envelope(err, system))
}
pub fn render_detailed_error_format(
format: &str,
err: &dyn DetailedError,
system: &str,
) -> Result<String> {
render_format(format, &build_detailed_error_envelope(err, system))
}