use std::{
borrow::Cow,
fs::File,
io::{BufWriter, Write, stdout},
path::PathBuf,
sync::Arc,
};
use serde::{Deserialize, Serialize};
use super::{Driver, Item};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct JsonConfig {
file: Option<PathBuf>,
pretty: Option<bool>,
tables: Option<bool>,
}
pub struct JsonDriver {
file: Box<dyn Write>,
pretty: bool,
tables: bool,
}
impl JsonDriver {
pub fn new(config: &JsonConfig) -> std::io::Result<Self> {
Ok(Self {
file: match &config.file {
Some(file) => Box::new(BufWriter::new(File::create(file)?)),
None => Box::new(stdout()),
},
pretty: config.pretty.unwrap_or_else(|| {
!config
.file
.as_ref()
.is_some_and(|file| file.ends_with(".ndjson"))
}),
tables: config.tables.unwrap_or_default(),
})
}
fn write_json<T>(&mut self, item: &T) -> std::io::Result<()>
where
T: Serialize + ?Sized,
{
if self.pretty {
serde_json::to_writer_pretty(&mut self.file, item)?;
} else {
serde_json::to_writer(&mut self.file, item)?;
}
writeln!(&mut self.file)
}
}
impl Driver for JsonDriver {
fn name(&self) -> Cow<'static, str> {
Cow::from("json")
}
fn write(&mut self, item: &Arc<Item>) {
self.write_json(item).unwrap(); }
fn can_serialize(&self) -> bool {
!self.tables
}
fn serialize(&mut self, item: &dyn erased_serde::Serialize) {
assert!(!self.tables);
self.write_json(item).unwrap(); }
fn flush(&mut self) {
let _ = self.file.flush();
}
}