reactive_graph_server/shared/output_format/
render_table.rs1use crate::shared::output_format::OutputFormatArgs;
2use crate::shared::output_format::OutputFormatArgsOptional;
3use reactive_graph_serde::error::SerializationError;
4use serde::Serialize;
5use std::process::exit;
6use table_to_html::HtmlTable;
7use tabled::Table;
8use tabled::Tabled;
9use tabled::settings::Style;
10use tabled::settings::Width;
11use tabled::settings::object::Rows;
12use thiserror::Error;
13use toml::map::Map;
14
15#[derive(Debug, Error)]
16pub enum RenderTableError {
17 #[error("Failed to serialize: {0}")]
18 SerializationError(#[from] SerializationError),
19 #[error("Not yet implemented")]
20 NotImplemented,
21}
22
23pub trait RenderTable {
24 fn render(&self, output_format: &OutputFormatArgs) -> Result<String, RenderTableError>;
25
26 fn do_print_table_and_exit(&self, output_format: &OutputFormatArgs) -> !;
27 fn print_table_and_exit(&self, output_format: &OutputFormatArgsOptional) -> !;
28}
29
30impl<T: Tabled + Serialize> RenderTable for Vec<T> {
31 fn render(&self, output_format: &OutputFormatArgs) -> Result<String, RenderTableError> {
32 match output_format {
33 OutputFormatArgs::Table => {
34 let table = Table::new(self).modify(Rows::new(1..), Width::wrap(40)).to_owned();
35 Ok(format!("{table}"))
36 }
37 OutputFormatArgs::HtmlTable => Ok(HtmlTable::with_header(Vec::<Vec<String>>::from(Table::builder(self)))
38 .to_string()
39 .trim()
40 .to_string()),
41 OutputFormatArgs::MarkdownTable => {
42 let table = Table::new(self).with(Style::markdown()).to_owned();
43 Ok(format!("{table}"))
44 }
45 OutputFormatArgs::Count => Ok(format!("{}", self.len())),
46 OutputFormatArgs::Json | OutputFormatArgs::Json5 => Ok(serde_json::to_string_pretty(self).map_err(SerializationError::Json)?),
47 OutputFormatArgs::Toml => {
48 let inner = toml::Value::try_from(self).map_err(SerializationError::Toml)?;
49 let mut map: Map<String, toml::Value> = Map::new();
50 let type_name = std::any::type_name::<T>().rsplit_once("::").unwrap_or_default().1.to_string();
51 map.insert(type_name, inner);
52 let table = toml::Value::Table(map);
53 Ok(toml::to_string_pretty(&table).map_err(SerializationError::Toml)?)
54 }
55 }
56 }
57
58 fn do_print_table_and_exit(&self, output_format: &OutputFormatArgs) -> ! {
59 match self.render(output_format) {
60 Ok(rendered_table) => {
61 println!("{rendered_table}");
62 exit(0);
63 }
64 Err(e) => {
65 eprintln!("{e}");
66 exit(1);
67 }
68 }
69 }
70 fn print_table_and_exit(&self, output_format: &OutputFormatArgsOptional) -> ! {
71 self.do_print_table_and_exit(&output_format.output_format.clone().unwrap_or_default())
72 }
73}