use std::fmt;
use std::io::{Read, Write};
use serde_json::error::Category;
use crate::model::IfcxFile;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReadErrorKind {
Io,
Syntax,
Data,
Eof,
}
#[derive(Debug)]
pub struct ReadError {
kind: ReadErrorKind,
line: usize,
column: usize,
source: serde_json::Error,
}
impl ReadError {
pub fn kind(&self) -> ReadErrorKind {
self.kind
}
pub fn line(&self) -> usize {
self.line
}
pub fn column(&self) -> usize {
self.column
}
}
impl From<serde_json::Error> for ReadError {
fn from(source: serde_json::Error) -> Self {
let kind = match source.classify() {
Category::Io => ReadErrorKind::Io,
Category::Syntax => ReadErrorKind::Syntax,
Category::Data => ReadErrorKind::Data,
Category::Eof => ReadErrorKind::Eof,
};
Self {
kind,
line: source.line(),
column: source.column(),
source,
}
}
}
impl fmt::Display for ReadError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "invalid IFCX file: {}", self.source)
}
}
impl std::error::Error for ReadError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.source)
}
}
#[derive(Debug)]
pub struct WriteError(serde_json::Error);
impl fmt::Display for WriteError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "could not write IFCX file: {}", self.0)
}
}
impl std::error::Error for WriteError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.0)
}
}
impl IfcxFile {
pub fn from_json_str(input: &str) -> Result<Self, ReadError> {
Ok(serde_json::from_str(input)?)
}
pub fn from_json_slice(input: &[u8]) -> Result<Self, ReadError> {
Ok(serde_json::from_slice(input)?)
}
pub fn from_json_reader(reader: impl Read) -> Result<Self, ReadError> {
Ok(serde_json::from_reader(reader)?)
}
pub fn to_json_string(&self) -> Result<String, WriteError> {
serde_json::to_string(self).map_err(WriteError)
}
pub fn to_json_string_pretty(&self) -> Result<String, WriteError> {
serde_json::to_string_pretty(self).map_err(WriteError)
}
pub fn to_json_writer(&self, writer: impl Write) -> Result<(), WriteError> {
serde_json::to_writer(writer, self).map_err(WriteError)
}
}