use crate::file::create_file;
use crate::{Error, Result};
use serde::Serialize;
use std::fs::OpenOptions;
use std::io::{BufWriter, Write};
use std::path::Path;
const JSON_LINES_BUFFER_SIZE: usize = 100;
pub fn save_json<T>(file: impl AsRef<Path>, data: &T) -> Result<()>
where
T: serde::Serialize,
{
save_json_impl(file.as_ref(), data, false)
}
pub fn save_json_pretty<T>(file: impl AsRef<Path>, data: &T) -> Result<()>
where
T: serde::Serialize,
{
save_json_impl(file.as_ref(), data, true)
}
fn save_json_impl<T>(file_path: &Path, data: &T, pretty: bool) -> Result<()>
where
T: serde::Serialize,
{
let file = create_file(file_path)?;
let res = if pretty {
serde_json::to_writer_pretty(file, data)
} else {
serde_json::to_writer(file, data)
};
res.map_err(|e| Error::JsonCantWrite((file_path, e).into()))?;
Ok(())
}
pub fn append_json_line<T: Serialize>(file: impl AsRef<Path>, value: &T) -> Result<()> {
let file_path = file.as_ref();
let json_string = serde_json::to_string(value).map_err(|e| Error::JsonCantWrite((file_path, e).into()))?;
let mut file = OpenOptions::new()
.create(true) .append(true) .open(file_path)
.map_err(|e| Error::FileCantOpen((file_path, e).into()))?;
writeln!(file, "{}", json_string).map_err(|e| Error::FileCantWrite((file_path, e).into()))?;
Ok(())
}
pub fn append_json_lines<'a, T, I>(file: impl AsRef<Path>, values: I) -> Result<()>
where
T: Serialize + 'a,
I: IntoIterator<Item = &'a T>,
{
let file_path = file.as_ref();
let file = OpenOptions::new()
.create(true) .append(true) .open(file_path)
.map_err(|e| Error::FileCantOpen((file_path, e).into()))?;
let mut writer = BufWriter::new(file);
let mut count = 0;
for value in values {
let json_string = serde_json::to_string(value).map_err(|e| Error::JsonCantWrite((file_path, e).into()))?;
writeln!(writer, "{}", json_string).map_err(|e| Error::FileCantWrite((file_path, e).into()))?;
count += 1;
if count % JSON_LINES_BUFFER_SIZE == 0 {
writer.flush().map_err(|e| Error::FileCantWrite((file_path, e).into()))?;
}
}
writer.flush().map_err(|e| Error::FileCantWrite((file_path, e).into()))?;
Ok(())
}