1use alloc::{
2 format,
3 string::{FromUtf8Error, String, ToString},
4 vec::Vec,
5};
6
7use crate::{Pointer, Token};
8use core::{
9 fmt::{Debug, Display, Formatter},
11 num::ParseIntError,
12};
13
14#[derive(Debug, PartialEq, Eq, Clone)]
17pub enum Error {
18 Index(IndexError),
21 Unresolvable(UnresolvableError),
25 NotFound(NotFoundError),
27 }
30
31impl Error {
32 pub fn is_index(&self) -> bool {
34 matches!(self, Error::Index(_))
35 }
36 pub fn is_unresolvable(&self) -> bool {
38 matches!(self, Error::Unresolvable(_))
39 }
40 pub fn is_not_found(&self) -> bool {
42 matches!(self, Error::NotFound(_))
43 }
44 }
49impl From<IndexError> for Error {
55 fn from(err: IndexError) -> Self {
56 Error::Index(err)
57 }
58}
59impl From<NotFoundError> for Error {
60 fn from(err: NotFoundError) -> Self {
61 Error::NotFound(err)
62 }
63}
64
65impl From<OutOfBoundsError> for Error {
66 fn from(err: OutOfBoundsError) -> Self {
67 Error::Index(IndexError::from(err))
68 }
69}
70
71impl From<UnresolvableError> for Error {
72 fn from(err: UnresolvableError) -> Self {
73 Error::Unresolvable(err)
74 }
75}
76
77impl Display for Error {
78 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
79 match self {
80 Error::Index(err) => Display::fmt(err, f),
81 Error::Unresolvable(err) => Display::fmt(err, f),
82 Error::NotFound(err) => Display::fmt(err, f),
83 }
85 }
86}
87
88#[cfg(feature = "std")]
89impl std::error::Error for Error {}
90
91#[derive(Clone, PartialEq, Eq, Debug)]
105pub struct UnresolvableError {
106 pub pointer: Pointer,
108 pub leaf: Option<Token>,
111}
112
113#[cfg(feature = "std")]
114impl std::error::Error for UnresolvableError {}
115
116impl UnresolvableError {
117 pub fn new(pointer: Pointer) -> Self {
119 let leaf = if pointer.count() >= 2 {
120 Some(pointer.get(pointer.count() - 2).unwrap())
121 } else {
122 None
123 };
124 Self { pointer, leaf }
125 }
126}
127
128impl Display for UnresolvableError {
129 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
130 write!(
131 f,
132 "can not resolve \"{}\" due to {} being a scalar value",
133 self.pointer,
134 self.leaf
135 .as_deref()
136 .map_or_else(|| "the root value".to_string(), |l| format!("\"{l}\""))
137 )
138 }
139}
140
141#[derive(PartialEq, Eq, Clone)]
144pub enum IndexError {
145 Parse(ParseError),
147 OutOfBounds(OutOfBoundsError),
150}
151impl Display for IndexError {
152 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
153 match self {
154 IndexError::Parse(err) => Display::fmt(&err, f),
155 IndexError::OutOfBounds(err) => Display::fmt(&err, f),
156 }
157 }
158}
159impl Debug for IndexError {
160 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
161 Display::fmt(self, f)
162 }
163}
164#[cfg(feature = "std")]
165impl std::error::Error for IndexError {}
166
167impl From<OutOfBoundsError> for IndexError {
168 fn from(err: OutOfBoundsError) -> Self {
169 IndexError::OutOfBounds(err)
170 }
171}
172
173#[derive(PartialEq, Eq, Clone)]
175pub struct ParseError {
176 pub source: ParseIntError,
178 pub token: Token,
180}
181
182impl Display for ParseError {
183 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
184 write!(f, "{}", self.source)
185 }
186}
187impl Debug for ParseError {
188 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
189 f.debug_struct("ParseError")
190 .field("source", &self.source)
191 .field("token", &self.token)
192 .finish()
193 }
194}
195#[cfg(feature = "std")]
196impl std::error::Error for ParseError {
197 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
198 Some(&self.source)
199 }
200}
201
202#[derive(Debug, PartialEq, Eq, Clone)]
205pub struct OutOfBoundsError {
206 pub len: usize,
208 pub index: usize,
210 pub token: Token,
212}
213#[cfg(feature = "std")]
214impl std::error::Error for OutOfBoundsError {}
215
216impl Display for OutOfBoundsError {
217 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
218 write!(f, "index {} out of bounds", self.index)
219 }
220}
221
222#[derive(Clone, PartialEq, Eq, Debug)]
224pub struct NotUtf8Error {
225 pub source: FromUtf8Error,
227 pub path: Vec<u8>,
229}
230
231impl core::fmt::Display for NotUtf8Error {
232 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
233 write!(f, "not utf8: {}", self.source)
234 }
235}
236#[cfg(feature = "std")]
237impl std::error::Error for NotUtf8Error {}
238
239#[derive(Debug, PartialEq, Eq, Clone)]
241pub enum MalformedPointerError {
242 NoLeadingSlash(String),
245 InvalidEncoding(String),
248 NotUtf8(NotUtf8Error),
250}
251impl From<NotUtf8Error> for MalformedPointerError {
252 fn from(err: NotUtf8Error) -> Self {
253 MalformedPointerError::NotUtf8(err)
254 }
255}
256
257impl From<FromUtf8Error> for MalformedPointerError {
258 fn from(err: FromUtf8Error) -> Self {
259 MalformedPointerError::NotUtf8(NotUtf8Error {
260 source: err,
261 path: Vec::new(),
262 })
263 }
264}
265impl Display for MalformedPointerError {
266 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
267 match self {
268 MalformedPointerError::NoLeadingSlash(s) => {
269 write!(
270 f,
271 "json pointer \"{s}\" is malformed due to missing starting slash",
272 )
273 }
274 MalformedPointerError::InvalidEncoding(s) => {
275 write!(f, "json pointer \"{s}\" is improperly encoded")
276 }
277 MalformedPointerError::NotUtf8(err) => {
278 write!(f, "json pointer is not UTF-8: {}", err.source)
279 }
280 }
281 }
282}
283
284#[cfg(feature = "std")]
285impl std::error::Error for MalformedPointerError {}
286
287#[derive(Debug, PartialEq, Eq, Clone)]
289pub struct NotFoundError {
290 pub pointer: Pointer,
292}
293impl NotFoundError {
294 pub fn new(pointer: Pointer) -> Self {
296 NotFoundError { pointer }
297 }
298}
299impl Display for NotFoundError {
300 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
301 write!(
302 f,
303 "the resource at json pointer \"{}\" was not found",
304 self.pointer
305 )
306 }
307}
308#[cfg(feature = "std")]
309impl std::error::Error for NotFoundError {}
310
311#[derive(Debug, PartialEq, Eq, Clone)]
314pub struct ReplaceTokenError {
315 pub index: usize,
317 pub count: usize,
319 pub pointer: Pointer,
321}
322#[cfg(feature = "std")]
323impl std::error::Error for ReplaceTokenError {}
324
325impl Display for ReplaceTokenError {
326 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
327 write!(
328 f,
329 "index {} is out of bounds ({}) for the pointer {}",
330 self.index, self.count, self.pointer
331 )
332 }
333}