use std::io::{Read, Write};
use crate::types::Result;
pub trait JsonIO: Sized {
fn from_json_reader<R: Read>(reader: R) -> Result<Self>;
fn to_json_writer<W: Write>(&self, writer: W) -> Result<()>;
fn from_json_string(json: &str) -> Result<Self>;
fn to_json_string(&self) -> Result<String>;
fn from_json_file(path: &str) -> Result<Self>;
fn to_json_file(&self, path: &str) -> Result<()>;
}
#[macro_export]
macro_rules! impl_json_io {
($type:ty) => {
impl $crate::io::JsonIO for $type {
fn from_json_reader<R: std::io::Read>(reader: R) -> $crate::types::Result<Self> {
let reader = std::io::BufReader::new(reader);
let json = serde_json::from_reader(reader)?;
let id = concat!(
paste::paste! { stringify!([<$type:lower>]) },
".schema.json"
);
let validator = jsonschema::options()
.with_retriever(&*$crate::assets::JSON_SCHEMA_RETRIEVER)
.build(&serde_json::json!({"$ref": id}))
.map_err(|e| $crate::types::Error::Parsing(&format!("Failed to build JSON Schema validator: {}", e)))?;
let errors: Vec<_> = validator.iter_errors(&json).collect();
if !errors.is_empty() {
let msg = errors
.into_iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join(", ");
return Err($crate::types::Error::Parsing(&format!(
"JSON Schema validation failed: {}",
msg
)));
}
serde_json::from_value(json).map_err(Into::into)
}
fn to_json_writer<W: std::io::Write>(&self, writer: W) -> $crate::types::Result<()> {
let writer = std::io::BufWriter::new(writer);
serde_json::to_writer(writer, self)?;
Ok(())
}
fn from_json_string(json: &str) -> $crate::types::Result<Self> {
Self::from_json_reader(json.as_bytes())
}
fn to_json_string(&self) -> $crate::types::Result<String> {
let mut buffer = Vec::new();
self.to_json_writer(&mut buffer)?;
String::from_utf8(buffer).map_err(Into::into)
}
fn from_json_file(path: &str) -> $crate::types::Result<Self> {
let file = std::fs::File::open(path)?;
let reader = std::io::BufReader::new(file);
Self::from_json_reader(reader)
}
fn to_json_file(&self, path: &str) -> $crate::types::Result<()> {
let file = std::fs::File::create(path)?;
let writer = std::io::BufWriter::new(file);
self.to_json_writer(writer)
}
}
};
}