Skip to main content

serde_sjson/
error.rs

1use std::{fmt, io};
2
3use crate::parser::Token;
4
5/// An alias for a `Result` with `serde_sjson::Error`.
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// A type encapsulating the different errors that might occurr
9/// during serialization or deserialization.
10#[derive(PartialEq)]
11pub struct Error {
12    inner: Box<ErrorImpl>,
13}
14
15#[derive(PartialEq)]
16struct ErrorImpl {
17    code: ErrorCode,
18    line: u32,
19    column: usize,
20    fragment: Option<String>,
21    token: Option<Token>,
22}
23
24#[derive(PartialEq)]
25pub(crate) enum ErrorCode {
26    // Generic error built from a message or different error
27    Message(String),
28    ExpectedArray,
29    ExpectedArrayEnd,
30    ExpectedArraySeparator,
31    ExpectedBoolean,
32    ExpectedEnum,
33    ExpectedFloat,
34    ExpectedInteger,
35    ExpectedMap,
36    ExpectedMapEnd,
37    ExpectedMapEquals,
38    ExpectedMapSeparator,
39    ExpectedNull,
40    ExpectedString,
41    ExpectedTopLevelObject,
42    ExpectedValue,
43    TrailingCharacters,
44    NonFiniteFloat,
45}
46
47impl fmt::Display for ErrorCode {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        match self {
50            ErrorCode::Message(msg) => f.write_str(msg),
51            ErrorCode::ExpectedArray => f.write_str("expected an array value"),
52            ErrorCode::ExpectedArrayEnd => f.write_str("expected an array end delimiter"),
53            ErrorCode::ExpectedArraySeparator => {
54                f.write_str("expected comma or newline between array entries")
55            }
56            ErrorCode::ExpectedBoolean => f.write_str("expected a boolean value"),
57            ErrorCode::ExpectedEnum => f.write_str("expected string or object"),
58            ErrorCode::ExpectedFloat => f.write_str("expected floating point number"),
59            ErrorCode::ExpectedInteger => f.write_str("expected an integer value"),
60            ErrorCode::ExpectedMap => f.write_str("expected an object"),
61            ErrorCode::ExpectedMapEnd => f.write_str("expected an object end delimiter"),
62            ErrorCode::ExpectedMapEquals => f.write_str("expected a '=' between key and value"),
63            ErrorCode::ExpectedMapSeparator => {
64                f.write_str("expected comma or newline between object entries")
65            }
66            ErrorCode::ExpectedNull => f.write_str("expected null"),
67            ErrorCode::ExpectedString => f.write_str("expected a string value"),
68            ErrorCode::ExpectedTopLevelObject => f.write_str("expected object at the top level"),
69            ErrorCode::ExpectedValue => f.write_str("expected a value"),
70            ErrorCode::TrailingCharacters => f.write_str("unexpected trailing characters"),
71            ErrorCode::NonFiniteFloat => f.write_str("got infinite floating point number"),
72        }
73    }
74}
75
76impl fmt::Display for ErrorImpl {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        if self.line == 0 {
79            fmt::Display::fmt(&self.code, f)
80        } else {
81            write!(
82                f,
83                "{} at line {} column {}",
84                self.code, self.line, self.column
85            )
86        }
87    }
88}
89
90impl fmt::Display for Error {
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        fmt::Display::fmt(&self.inner, f)
93    }
94}
95
96impl fmt::Debug for Error {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        write!(
99            f,
100            "Error({:?}, line: {}, column: {}, fragment: {:?}, token: {:?})",
101            self.inner.code.to_string(),
102            self.inner.line,
103            self.inner.column,
104            self.inner.fragment,
105            self.inner.token,
106        )
107    }
108}
109
110impl serde::de::Error for Error {
111    fn custom<T>(msg: T) -> Self
112    where
113        T: ToString,
114    {
115        let inner = Box::new(ErrorImpl {
116            code: ErrorCode::Message(msg.to_string()),
117            line: 0,
118            column: 0,
119            fragment: None,
120            token: None,
121        });
122        Self { inner }
123    }
124}
125
126impl serde::ser::Error for Error {
127    fn custom<T>(msg: T) -> Self
128    where
129        T: ToString,
130    {
131        let inner = Box::new(ErrorImpl {
132            code: ErrorCode::Message(msg.to_string()),
133            line: 0,
134            column: 0,
135            fragment: None,
136            token: None,
137        });
138        Self { inner }
139    }
140}
141
142impl std::error::Error for Error {}
143
144impl Error {
145    pub(crate) fn new(code: ErrorCode, line: u32, column: usize, fragment: Option<String>) -> Self {
146        Self {
147            inner: Box::new(ErrorImpl {
148                code,
149                line,
150                column,
151                fragment,
152                token: None,
153            }),
154        }
155    }
156    pub(crate) fn with_token(
157        code: ErrorCode,
158        line: u32,
159        column: usize,
160        fragment: Option<String>,
161        token: Token,
162    ) -> Self {
163        Self {
164            inner: Box::new(ErrorImpl {
165                code,
166                line,
167                column,
168                fragment,
169                token: Some(token),
170            }),
171        }
172    }
173}
174
175impl From<io::Error> for Error {
176    fn from(err: io::Error) -> Self {
177        Self::new(ErrorCode::Message(format!("{}", err)), 0, 0, None)
178    }
179}