1use std::fmt;
4use std::io::{Read, Write};
5
6use serde_json::error::Category;
7
8use crate::model::IfcxFile;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum ReadErrorKind {
13 Io,
15 Syntax,
17 Data,
19 Eof,
21}
22
23#[derive(Debug)]
25pub struct ReadError {
26 kind: ReadErrorKind,
27 line: usize,
28 column: usize,
29 source: serde_json::Error,
30}
31
32impl ReadError {
33 pub fn kind(&self) -> ReadErrorKind {
34 self.kind
35 }
36
37 pub fn line(&self) -> usize {
39 self.line
40 }
41
42 pub fn column(&self) -> usize {
44 self.column
45 }
46}
47
48impl From<serde_json::Error> for ReadError {
49 fn from(source: serde_json::Error) -> Self {
50 let kind = match source.classify() {
51 Category::Io => ReadErrorKind::Io,
52 Category::Syntax => ReadErrorKind::Syntax,
53 Category::Data => ReadErrorKind::Data,
54 Category::Eof => ReadErrorKind::Eof,
55 };
56 Self {
57 kind,
58 line: source.line(),
59 column: source.column(),
60 source,
61 }
62 }
63}
64
65impl fmt::Display for ReadError {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 write!(f, "invalid IFCX file: {}", self.source)
68 }
69}
70
71impl std::error::Error for ReadError {
72 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
73 Some(&self.source)
74 }
75}
76
77#[derive(Debug)]
79pub struct WriteError(serde_json::Error);
80
81impl fmt::Display for WriteError {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "could not write IFCX file: {}", self.0)
84 }
85}
86
87impl std::error::Error for WriteError {
88 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
89 Some(&self.0)
90 }
91}
92
93impl IfcxFile {
94 pub fn from_json_str(input: &str) -> Result<Self, ReadError> {
95 Ok(serde_json::from_str(input)?)
96 }
97
98 pub fn from_json_slice(input: &[u8]) -> Result<Self, ReadError> {
99 Ok(serde_json::from_slice(input)?)
100 }
101
102 pub fn from_json_reader(reader: impl Read) -> Result<Self, ReadError> {
104 Ok(serde_json::from_reader(reader)?)
105 }
106
107 pub fn to_json_string(&self) -> Result<String, WriteError> {
108 serde_json::to_string(self).map_err(WriteError)
109 }
110
111 pub fn to_json_string_pretty(&self) -> Result<String, WriteError> {
112 serde_json::to_string_pretty(self).map_err(WriteError)
113 }
114
115 pub fn to_json_writer(&self, writer: impl Write) -> Result<(), WriteError> {
116 serde_json::to_writer(writer, self).map_err(WriteError)
117 }
118}