reactive_graph_table_model/
container.rs

1use std::fmt::Display;
2use std::fmt::Formatter;
3use std::marker::PhantomData;
4use std::vec::IntoIter;
5use table_to_html::HtmlTable;
6use tabled::Table;
7use tabled::Tabled;
8use tabled::settings::Style;
9
10pub trait TableContainer: Display {
11    fn table(&self) -> Table;
12
13    fn markdown_table(&self) -> Table;
14
15    fn html_table(&self) -> HtmlTable;
16}
17
18pub trait TableOptions: Sized {
19    fn options(table: &mut Table) -> &mut Table;
20}
21
22#[derive(Debug)]
23pub enum TableOutputFormat {
24    Table,
25    MarkdownTable,
26    HtmlTable,
27}
28
29#[derive(Clone, Debug)]
30pub enum TableInlineFormat {
31    Table,
32    Html,
33}
34
35pub trait TableInlineFormatSetter {
36    fn set_table_inline_format(&mut self, table_inline_format: TableInlineFormat);
37}
38
39impl Default for TableInlineFormat {
40    fn default() -> Self {
41        Self::Table
42    }
43}
44
45pub struct DefaultTableOptions {}
46
47impl TableOptions for DefaultTableOptions {
48    fn options(table: &mut Table) -> &mut Table {
49        table.with(Style::extended())
50    }
51}
52
53pub struct DefaultTableContainer<S, T: Clone + Tabled + From<S> + TableInlineFormatSetter, O: TableOptions>(
54    pub(crate) Vec<T>,
55    TableOutputFormat,
56    PhantomData<S>,
57    PhantomData<O>,
58);
59
60impl<S: 'static, T: Clone + Tabled + From<S> + TableInlineFormatSetter + 'static, O: TableOptions + 'static> DefaultTableContainer<S, T, O> {
61    pub fn into_boxed(self) -> Box<DefaultTableContainer<S, T, O>> {
62        Box::new(self)
63    }
64
65    pub fn into_html_table(mut self) -> Self {
66        self.0.iter_mut().for_each(|item| item.set_table_inline_format(TableInlineFormat::Html));
67        self.1 = TableOutputFormat::HtmlTable;
68        self
69    }
70
71    pub fn into_markdown_table(mut self) -> Self {
72        self.0.iter_mut().for_each(|item| item.set_table_inline_format(TableInlineFormat::Html));
73        self.1 = TableOutputFormat::MarkdownTable;
74        self
75    }
76}
77
78impl<S, T: Clone + Tabled + From<S> + TableInlineFormatSetter, O: TableOptions> TableContainer for DefaultTableContainer<S, T, O> {
79    fn table(&self) -> Table {
80        let mut table = Table::new(self.0.to_vec().iter());
81        O::options(&mut table).to_owned()
82    }
83
84    fn markdown_table(&self) -> Table {
85        Table::new(self.0.to_vec().iter()).with(Style::markdown()).to_owned()
86    }
87
88    fn html_table(&self) -> HtmlTable {
89        let items = self.0.to_vec();
90        HtmlTable::with_header(Vec::<Vec<String>>::from(Table::builder(&items)))
91    }
92}
93
94impl<S, T: Clone + Tabled + From<S> + TableInlineFormatSetter, O: TableOptions> From<Vec<S>> for DefaultTableContainer<S, T, O> {
95    fn from(entries: Vec<S>) -> Self {
96        DefaultTableContainer::<S, T, O>(entries.into_iter().map(From::from).collect(), TableOutputFormat::Table, PhantomData, PhantomData)
97    }
98}
99
100impl<S, T: Clone + Tabled + From<S> + TableInlineFormatSetter, O: TableOptions> From<S> for DefaultTableContainer<S, T, O> {
101    fn from(s: S) -> Self {
102        DefaultTableContainer::<S, T, O>(vec![s.into()], TableOutputFormat::Table, PhantomData, PhantomData)
103    }
104}
105
106impl<S, T: Clone + Tabled + From<S> + TableInlineFormatSetter, O: TableOptions> From<IntoIter<S>> for DefaultTableContainer<S, T, O> {
107    fn from(iter: IntoIter<S>) -> Self {
108        DefaultTableContainer::<S, T, O>(iter.map(From::from).collect(), TableOutputFormat::Table, PhantomData, PhantomData)
109    }
110}
111
112impl<S, T: Clone + Tabled + From<S> + TableInlineFormatSetter, O: TableOptions> FromIterator<S> for DefaultTableContainer<S, T, O> {
113    fn from_iter<TT: IntoIterator<Item = S>>(iter: TT) -> Self {
114        let entries = iter.into_iter().map(From::from).collect();
115        DefaultTableContainer::<S, T, O>(entries, TableOutputFormat::Table, PhantomData, PhantomData)
116    }
117}
118
119impl<S, T: Clone + Tabled + From<S> + TableInlineFormatSetter, O: TableOptions> Display for DefaultTableContainer<S, T, O> {
120    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
121        match self.1 {
122            TableOutputFormat::Table => {
123                write!(f, "{}", self.table())
124            }
125            TableOutputFormat::MarkdownTable => {
126                write!(f, "{}", self.markdown_table())
127            }
128            TableOutputFormat::HtmlTable => {
129                write!(f, "{}", self.html_table().to_string().trim())
130            }
131        }
132    }
133}