use std::io::Stdout;
use serde::Serialize;
use strum::Display;
use crate::cli::output::{CsvWriter, JsonLinesWriter, JsonWriter, Writer};
#[derive(clap::ValueEnum, Clone, Copy, Display, Default, Eq, PartialEq)]
pub enum OutputFormat {
#[strum(serialize = "csv")]
#[default]
Csv,
#[strum(serialize = "json")]
Json,
#[strum(serialize = "json-lines")]
JsonLines,
}
impl Writer for OutputFormat {
fn write_typenames<I>(&self, names: I) -> anyhow::Result<()>
where
I: Iterator<Item = String>,
{
match self {
OutputFormat::Csv => CsvWriter.write_typenames(names),
OutputFormat::Json => JsonWriter.write_typenames(names),
OutputFormat::JsonLines => JsonLinesWriter.write_typenames(names),
}
}
}
impl OutputFormat {
pub fn create_writer<T>(&self) -> anyhow::Result<OutputWriter<T>>
where
T: Serialize,
{
match self {
OutputFormat::Csv => {
let csv_writer = csv::WriterBuilder::new()
.flexible(false)
.from_writer(std::io::stdout());
Ok(OutputWriter::Csv(Box::new(csv_writer)))
}
OutputFormat::Json => Ok(OutputWriter::Json(Vec::new())),
OutputFormat::JsonLines => Ok(OutputWriter::JsonLines),
}
}
}
pub enum OutputWriter<T>
where
T: Serialize,
{
Csv(Box<csv::Writer<Stdout>>),
Json(Vec<T>),
JsonLines,
}
impl<T> OutputWriter<T>
where
T: Serialize,
{
pub fn write(&mut self, obj: T) -> anyhow::Result<()> {
match self {
OutputWriter::Csv(writer) => {
writer.serialize(obj)?;
writer.flush()?;
}
OutputWriter::Json(items) => {
items.push(obj);
}
OutputWriter::JsonLines => {
println!("{}", serde_json::to_string(&obj)?);
}
}
Ok(())
}
}
impl<T> Drop for OutputWriter<T>
where
T: Serialize,
{
fn drop(&mut self) {
match self {
OutputWriter::Csv(_) => (),
OutputWriter::Json(items) => {
println!("{}", serde_json::to_string_pretty(&items).unwrap());
}
OutputWriter::JsonLines => (),
}
}
}