use std::{borrow::Cow, path::Path, sync::Arc};
use clap::ValueEnum;
use serde::{Deserialize, Serialize};
use crate::output::{
cairo::{CairoConfig, CairoDriver},
csv::{CsvConfig, CsvDriver},
html::{HtmlConfig, HtmlDriver},
json::{JsonConfig, JsonDriver},
spv::{SpvConfig, SpvDriver},
text::{TextConfig, TextDriver},
};
use super::{page::PageSetup, Item};
pub trait Driver {
fn name(&self) -> Cow<'static, str>;
fn write(&mut self, item: &Arc<Item>);
fn setup(&mut self, page_setup: &PageSetup) -> bool {
let _ = page_setup;
false
}
fn flush(&mut self) {}
fn handles_show(&self) -> bool {
false
}
fn handles_groups(&self) -> bool {
false
}
}
impl Driver for Box<dyn Driver> {
fn name(&self) -> Cow<'static, str> {
(**self).name()
}
fn write(&mut self, item: &Arc<Item>) {
(**self).write(item);
}
fn setup(&mut self, page_setup: &PageSetup) -> bool {
(**self).setup(page_setup)
}
fn flush(&mut self) {
(**self).flush();
}
fn handles_show(&self) -> bool {
(**self).handles_show()
}
fn handles_groups(&self) -> bool {
(**self).handles_groups()
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(tag = "driver", rename_all = "snake_case")]
pub enum Config {
Text(TextConfig),
Pdf(CairoConfig),
Html(HtmlConfig),
Json(JsonConfig),
Csv(CsvConfig),
Spv(SpvConfig),
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, ValueEnum)]
#[serde(rename_all = "snake_case")]
pub enum DriverType {
Text,
Pdf,
Html,
Csv,
Json,
Spv,
}
impl dyn Driver {
pub fn new(config: &Config) -> anyhow::Result<Box<Self>> {
match config {
Config::Text(text_config) => Ok(Box::new(TextDriver::new(text_config)?)),
Config::Pdf(cairo_config) => Ok(Box::new(CairoDriver::new(cairo_config)?)),
Config::Html(html_config) => Ok(Box::new(HtmlDriver::new(html_config)?)),
Config::Csv(csv_config) => Ok(Box::new(CsvDriver::new(csv_config)?)),
Config::Json(json_config) => Ok(Box::new(JsonDriver::new(json_config)?)),
Config::Spv(spv_config) => Ok(Box::new(SpvDriver::new(spv_config)?)),
}
}
pub fn driver_type_from_filename(file: impl AsRef<Path>) -> Option<&'static str> {
match file.as_ref().extension()?.to_str()? {
"txt" | "text" => Some("text"),
"pdf" => Some("pdf"),
"htm" | "html" => Some("html"),
"csv" => Some("csv"),
"json" => Some("json"),
"spv" => Some("spv"),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use serde::Serialize;
use crate::output::driver::Config;
#[test]
fn toml() {
let config = r#"driver = "text"
file = "filename.text"
"#;
let toml: Config = toml::from_str(config).unwrap();
println!("{}", toml::to_string_pretty(&toml).unwrap());
#[derive(Serialize)]
struct Map<'a> {
file: &'a str,
}
println!(
"{}",
toml::to_string_pretty(&Map { file: "filename" }).unwrap()
);
}
}