use std::fs::File;
use std::fs::OpenOptions;
use std::io::BufReader;
use std::io::BufWriter;
use std::path::Path;
pub use native_json_macro::*;
pub use serde::de::DeserializeOwned;
pub use serde::{Deserialize, Serialize};
pub use serde_json::from_str as parse;
pub use serde_json::Error;
pub fn is_default<T: Default + PartialEq>(t: &T) -> bool {
t == &T::default()
}
pub trait JSON: Serialize {
fn string(&self) -> anyhow::Result<String> {
self.stringify(0)
}
fn stringify(&self, indent: usize) -> anyhow::Result<String> {
if indent == 0 {
return Ok(serde_json::to_string(self)?);
}
let buf = Vec::new();
let spaces = vec![' ' as u8; indent];
let formatter = serde_json::ser::PrettyFormatter::with_indent(&spaces);
let mut ser = serde_json::Serializer::with_formatter(buf, formatter);
self.serialize(&mut ser)?;
let output = String::from_utf8(ser.into_inner())?;
Ok(output)
}
}
impl<T> JSON for T where T: Serialize {}
pub fn read<T, P: AsRef<Path>>(path: P) -> anyhow::Result<T>
where
T: DeserializeOwned,
{
let file = File::open(path)?;
let reader = BufReader::new(file);
let value = serde_json::from_reader(reader)?;
Ok(value)
}
pub fn write<T, P: AsRef<Path>>(path: P, value: &T) -> anyhow::Result<()>
where
T: Serialize,
{
let file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(path)?;
let writer = BufWriter::new(file);
Ok(serde_json::to_writer_pretty(writer, value)?)
}
pub struct Writer<'a> {
path: &'a Path,
indent: usize,
}
impl<'a> Writer<'a> {
pub fn indent(mut self, n: usize) -> Self {
self.indent = n;
self
}
pub fn write<T>(&self, value: &T) -> anyhow::Result<()>
where
T: Serialize,
{
let spaces = vec![' ' as u8; self.indent];
let file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(self.path)?;
let writer = BufWriter::new(file);
let formatter = serde_json::ser::PrettyFormatter::with_indent(&spaces);
let mut ser = serde_json::Serializer::with_formatter(writer, formatter);
Ok(value.serialize(&mut ser)?)
}
}
pub fn writer<'a, P>(path: &'a P) -> Writer<'a>
where
P: AsRef<Path>,
{
Writer {
path: path.as_ref(),
indent: 2,
}
}