rsonpath_syntax/num/
error.rs

1//! Error types for arithmetic, conversion, and parse operations
2//! on [`JsonInt`] and [`JsonUInt`].
3
4use crate::num::{JsonInt, JsonUInt};
5use std::{
6    fmt::{self, Display},
7    num::IntErrorKind,
8};
9use thiserror::Error;
10
11/// Errors raised when trying to convert between JSON integer types
12/// or between a JSON int and a regular Rust int, or when performing
13/// arithmetic on JSON ints that would over-/underflow.
14#[derive(Debug, PartialEq, Error, Clone)]
15pub struct JsonIntOverflowError {
16    kind: JsonIntOverflowKind,
17}
18
19/// Errors raised when trying to parse JSON integer types from strings.
20#[derive(Debug, PartialEq, Eq, Error, Clone)]
21pub struct JsonIntParseError {
22    kind: JsonIntParseErrorKind,
23}
24
25/// Errors raised when trying to convert between [`JsonFloat`](crate::num::JsonFloat) and
26/// regular Rust floating point numbers.
27#[derive(Debug, PartialEq, Error, Clone)]
28pub struct JsonFloatConvertError {
29    kind: JsonFloatConvertErrorKind,
30}
31
32/// Errors raised when trying to parse [`JsonFloat`](crate::num::JsonFloat) values from strings.
33#[derive(Debug, PartialEq, Eq, Error, Clone)]
34pub struct JsonFloatParseError {
35    kind: JsonFloatParseErrorKind,
36}
37
38impl JsonIntOverflowError {
39    pub(crate) fn int_pos_overflow(src: i64) -> Self {
40        Self {
41            kind: JsonIntOverflowKind::IntPos(src),
42        }
43    }
44
45    pub(crate) fn int_pos_overflow_u(src: u64) -> Self {
46        Self {
47            kind: JsonIntOverflowKind::IntPosU(src),
48        }
49    }
50
51    pub(crate) fn int_neg_overflow(src: i64) -> Self {
52        Self {
53            kind: JsonIntOverflowKind::IntNeg(src),
54        }
55    }
56
57    pub(crate) fn uint_pos_overflow(src: u64) -> Self {
58        Self {
59            kind: JsonIntOverflowKind::UIntPos(src),
60        }
61    }
62
63    pub(crate) fn negative_uint(src: i64) -> Self {
64        Self {
65            kind: JsonIntOverflowKind::UIntNeg(src),
66        }
67    }
68
69    pub(crate) fn zero_non_zero_uint() -> Self {
70        Self {
71            kind: JsonIntOverflowKind::NonZeroUIntZero,
72        }
73    }
74
75    pub(crate) fn fractional(src: f64) -> Self {
76        Self {
77            kind: JsonIntOverflowKind::Fractional(src),
78        }
79    }
80
81    pub(crate) fn int_float_pos_overflow(src: f64) -> Self {
82        Self {
83            kind: JsonIntOverflowKind::FloatPos(src),
84        }
85    }
86
87    pub(crate) fn int_float_neg_overflow(src: f64) -> Self {
88        Self {
89            kind: JsonIntOverflowKind::FloatNeg(src),
90        }
91    }
92}
93
94impl JsonIntParseError {
95    pub(crate) fn int_parse_error(src: &str, err: &IntErrorKind) -> Self {
96        Self {
97            kind: match err {
98                IntErrorKind::PosOverflow => JsonIntParseErrorKind::IntPosOverflow(src.to_string()),
99                IntErrorKind::NegOverflow => JsonIntParseErrorKind::IntNegOverflow(src.to_string()),
100                IntErrorKind::Zero => unreachable!(), // Zero is always a valid JsonInt value.
101                _ => JsonIntParseErrorKind::InvalidFormat(src.to_string()),
102            },
103        }
104    }
105
106    pub(crate) fn parse_conversion_err(src: &str, err: &JsonIntOverflowError) -> Self {
107        Self {
108            kind: match err.kind {
109                JsonIntOverflowKind::IntPosU(_) | JsonIntOverflowKind::IntPos(_) => {
110                    JsonIntParseErrorKind::IntPosOverflow(src.to_string())
111                }
112                JsonIntOverflowKind::IntNeg(_) => JsonIntParseErrorKind::IntNegOverflow(src.to_string()),
113                JsonIntOverflowKind::UIntPos(_) => JsonIntParseErrorKind::UIntPosOverflow(src.to_string()),
114                JsonIntOverflowKind::UIntNeg(_) => JsonIntParseErrorKind::UIntNegOverflow(src.to_string()),
115                JsonIntOverflowKind::NonZeroUIntZero => JsonIntParseErrorKind::NonZeroUIntZero(src.to_string()),
116                JsonIntOverflowKind::Fractional(_)
117                | JsonIntOverflowKind::FloatPos(_)
118                | JsonIntOverflowKind::FloatNeg(_) => JsonIntParseErrorKind::InvalidFormat(src.to_string()),
119            },
120        }
121    }
122
123    pub(crate) fn uint_parse_error(src: &str, err: &IntErrorKind) -> Self {
124        Self {
125            kind: match err {
126                IntErrorKind::PosOverflow => JsonIntParseErrorKind::UIntPosOverflow(src.to_string()),
127                IntErrorKind::NegOverflow => JsonIntParseErrorKind::UIntNegOverflow(src.to_string()),
128                IntErrorKind::Zero => unreachable!(), // Zero is always a valid JsonUInt value.
129                _ => JsonIntParseErrorKind::InvalidFormat(src.to_string()),
130            },
131        }
132    }
133
134    pub(crate) fn non_zero_uint_parse_error(src: &str, err: &IntErrorKind) -> Self {
135        Self {
136            kind: match err {
137                IntErrorKind::PosOverflow => JsonIntParseErrorKind::UIntPosOverflow(src.to_string()),
138                IntErrorKind::NegOverflow => JsonIntParseErrorKind::UIntNegOverflow(src.to_string()),
139                IntErrorKind::Zero => JsonIntParseErrorKind::NonZeroUIntZero(src.to_string()),
140                _ => JsonIntParseErrorKind::InvalidFormat(src.to_string()),
141            },
142        }
143    }
144}
145
146impl JsonFloatConvertError {
147    pub(crate) fn infinite_or_nan(src: f64) -> Self {
148        Self {
149            kind: JsonFloatConvertErrorKind::InfinityOrNaN(src),
150        }
151    }
152}
153
154impl JsonFloatParseError {
155    pub(crate) fn infinite_or_nan(src: &str) -> Self {
156        Self {
157            kind: JsonFloatParseErrorKind::InfinityOrNaN(src.to_string()),
158        }
159    }
160
161    pub(crate) fn leading_plus_sign(src: &str) -> Self {
162        Self {
163            kind: JsonFloatParseErrorKind::LeadingPlusSign(src.to_string()),
164        }
165    }
166
167    pub(crate) fn leading_zeros(src: &str) -> Self {
168        Self {
169            kind: JsonFloatParseErrorKind::LeadingZeros(src.to_string()),
170        }
171    }
172
173    pub(crate) fn nothing_after_decimal_point(src: &str) -> Self {
174        Self {
175            kind: JsonFloatParseErrorKind::NothingAfterDecimalPoint(src.to_string()),
176        }
177    }
178
179    pub(crate) fn nothing_before_decimal_point(src: &str) -> Self {
180        Self {
181            kind: JsonFloatParseErrorKind::NothingBeforeDecimalPoint(src.to_string()),
182        }
183    }
184
185    pub(crate) fn f64_parse_error(src: &str) -> Self {
186        Self {
187            kind: JsonFloatParseErrorKind::InvalidFormat(src.to_string()),
188        }
189    }
190}
191
192#[derive(Debug, PartialEq, Clone)]
193enum JsonIntOverflowKind {
194    IntPos(i64),
195    IntPosU(u64),
196    IntNeg(i64),
197    UIntPos(u64),
198    UIntNeg(i64),
199    NonZeroUIntZero,
200    Fractional(f64),
201    FloatPos(f64),
202    FloatNeg(f64),
203}
204
205#[derive(Debug, PartialEq, Eq, Clone)]
206enum JsonIntParseErrorKind {
207    IntPosOverflow(String),
208    IntNegOverflow(String),
209    UIntPosOverflow(String),
210    UIntNegOverflow(String),
211    NonZeroUIntZero(String),
212    InvalidFormat(String),
213}
214
215#[derive(Debug, PartialEq, Clone)]
216enum JsonFloatConvertErrorKind {
217    InfinityOrNaN(f64),
218}
219
220#[derive(Debug, PartialEq, Eq, Clone)]
221enum JsonFloatParseErrorKind {
222    InfinityOrNaN(String),
223    NothingBeforeDecimalPoint(String),
224    NothingAfterDecimalPoint(String),
225    LeadingPlusSign(String),
226    LeadingZeros(String),
227    InvalidFormat(String),
228}
229
230impl Display for JsonIntOverflowError {
231    #[inline(always)]
232    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233        self.kind.fmt(f)
234    }
235}
236
237impl Display for JsonIntParseError {
238    #[inline(always)]
239    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240        self.kind.fmt(f)
241    }
242}
243
244impl Display for JsonFloatConvertError {
245    #[inline(always)]
246    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247        self.kind.fmt(f)
248    }
249}
250
251impl Display for JsonFloatParseError {
252    #[inline(always)]
253    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254        self.kind.fmt(f)
255    }
256}
257
258impl Display for JsonIntOverflowKind {
259    #[inline]
260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261        match self {
262            Self::IntPos(src) => write!(
263                f,
264                "value {src} is above the range of JsonInt values [{}..{}]",
265                JsonInt::MIN,
266                JsonInt::MAX
267            ),
268            Self::IntPosU(src) => write!(
269                f,
270                "value {src} is above the range of JsonInt values [{}..{}]",
271                JsonInt::MIN,
272                JsonInt::MAX
273            ),
274            Self::IntNeg(src) => write!(
275                f,
276                "value {src} is below the range of JsonInt values [{}..{}]",
277                JsonInt::MIN,
278                JsonInt::MAX
279            ),
280            Self::UIntPos(src) => write!(
281                f,
282                "value {src} is above the range of JsonUInt values [0..{}]",
283                JsonUInt::MAX
284            ),
285            Self::UIntNeg(src) => {
286                write!(f, "attempt to convert a negative value {src} into a JsonUInt",)
287            }
288            Self::NonZeroUIntZero => {
289                write!(f, "attempt to convert a zero value into a JsonNonZeroUInt",)
290            }
291            Self::Fractional(src) => write!(f, "attempt to convert a fractional value {src} into a JsonInt"),
292            Self::FloatPos(src) => write!(
293                f,
294                "floating-point value {src} is above the range of JsonInt values [{}..{}]",
295                JsonInt::MIN,
296                JsonInt::MAX
297            ),
298            Self::FloatNeg(src) => write!(
299                f,
300                "floating-point value {src} is below the range of JsonInt values [{}..{}]",
301                JsonInt::MIN,
302                JsonInt::MAX
303            ),
304        }
305    }
306}
307
308impl Display for JsonIntParseErrorKind {
309    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310        match self {
311            Self::IntPosOverflow(src) => write!(
312                f,
313                "string '{src}' represents a value above the range of JsonInt values [{}..{}]",
314                JsonInt::MIN,
315                JsonInt::MAX
316            ),
317            Self::IntNegOverflow(src) => write!(
318                f,
319                "string '{src}' represents a value below the range of JsonInt values [{}..{}]",
320                JsonInt::MIN,
321                JsonInt::MAX
322            ),
323            Self::UIntPosOverflow(src) => write!(
324                f,
325                "string '{src}' represents a value above the range of JsonUInt values [0..{}]",
326                JsonUInt::MAX
327            ),
328            Self::UIntNegOverflow(src) => {
329                write!(
330                    f,
331                    "string '{src}' represents a value below the range of JsonUInt values [0..{}]",
332                    JsonUInt::MAX
333                )
334            }
335            Self::NonZeroUIntZero(src) => write!(
336                f,
337                "string '{src}' represents a zero value, which is not a valid JsonNonZeroUInt"
338            ),
339            Self::InvalidFormat(src) => write!(f, "string '{src}' is not a valid representation of a JSON integer"),
340        }
341    }
342}
343
344impl Display for JsonFloatConvertErrorKind {
345    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346        match self {
347            Self::InfinityOrNaN(src) => write!(f, "cannot convert from a non-finite float {src}"),
348        }
349    }
350}
351
352impl Display for JsonFloatParseErrorKind {
353    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354        match self {
355            Self::InfinityOrNaN(src) => {
356                write!(
357                    f,
358                    "string '{src}' is not a valid JsonFloat as it is not a finite number"
359                )
360            }
361            Self::NothingBeforeDecimalPoint(src) => write!(f, "missing digits before the decimal point in '{src}'"),
362            Self::NothingAfterDecimalPoint(src) => write!(f, "missing digits after the decimal point in '{src}'"),
363            Self::LeadingPlusSign(src) => write!(f, "string '{src}' includes a leading plus sign"),
364            Self::LeadingZeros(src) => write!(f, "string '{src}' includes leading zeros"),
365            Self::InvalidFormat(src) => write!(f, "string '{src}' is not a valid representation of a float"),
366        }
367    }
368}