Skip to main content

rama_json/
error.rs

1use std::fmt;
2
3/// Error produced while parsing, selecting, or rewriting JSON.
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct JsonError {
6    kind: JsonErrorKind,
7    offset: Option<usize>,
8}
9
10impl JsonError {
11    /// Creates an error without a byte offset.
12    #[must_use]
13    pub const fn new(kind: JsonErrorKind) -> Self {
14        Self { kind, offset: None }
15    }
16
17    /// Creates an error at an absolute input byte offset.
18    #[must_use]
19    pub const fn at(kind: JsonErrorKind, offset: usize) -> Self {
20        Self {
21            kind,
22            offset: Some(offset),
23        }
24    }
25
26    /// The reason for the failure.
27    #[must_use]
28    pub const fn kind(&self) -> &JsonErrorKind {
29        &self.kind
30    }
31
32    /// Absolute byte offset of the failure, when known.
33    #[must_use]
34    pub const fn offset(&self) -> Option<usize> {
35        self.offset
36    }
37}
38
39/// Reason for a JSON failure.
40#[derive(Debug, Clone, PartialEq, Eq)]
41#[non_exhaustive]
42pub enum JsonErrorKind {
43    /// Input ended before a complete JSON token or document was available.
44    UnexpectedEnd,
45    /// A byte is not valid at the current position.
46    UnexpectedByte(u8),
47    /// A token appeared where the JSON grammar does not allow it.
48    UnexpectedToken(&'static str),
49    /// A string literal contains an invalid escape sequence.
50    InvalidEscape,
51    /// A string literal contains a control character.
52    ControlCharacterInString,
53    /// A string literal is not valid UTF-8.
54    InvalidUtf8,
55    /// A number literal does not follow the JSON number grammar.
56    InvalidNumber,
57    /// A JSON value could not be serialized.
58    SerializationFailure,
59    /// A JSON value could not be deserialized.
60    DeserializationFailure,
61    /// More than one top-level JSON value was found.
62    TrailingValue,
63    /// Buffered input exceeded the configured tokenizer limit.
64    InputBufferLimitExceeded(usize),
65    /// A JSONPath expression was empty.
66    EmptyPath,
67    /// A JSONPath expression did not start with `$`.
68    MissingRoot,
69    /// A JSONPath expression contains a feature not implemented yet.
70    UnsupportedJsonPath(&'static str),
71    /// A JSON rewrite operation is not supported yet.
72    UnsupportedRewrite(&'static str),
73    /// A JSONPath expression contains malformed syntax.
74    InvalidJsonPath(&'static str),
75    /// A selected JSON value exceeded the configured capture limit.
76    CaptureLimitExceeded(usize),
77}
78
79impl fmt::Display for JsonError {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        match &self.kind {
82            JsonErrorKind::UnexpectedEnd => f.write_str("unexpected end of JSON input")?,
83            JsonErrorKind::UnexpectedByte(b) => write!(f, "unexpected byte {b:#04x}")?,
84            JsonErrorKind::UnexpectedToken(token) => write!(f, "unexpected JSON token {token}")?,
85            JsonErrorKind::InvalidEscape => f.write_str("invalid JSON string escape")?,
86            JsonErrorKind::ControlCharacterInString => {
87                f.write_str("control character in JSON string")?
88            }
89            JsonErrorKind::InvalidUtf8 => f.write_str("JSON string is not valid UTF-8")?,
90            JsonErrorKind::InvalidNumber => f.write_str("invalid JSON number")?,
91            JsonErrorKind::SerializationFailure => f.write_str("JSON serialization failure")?,
92            JsonErrorKind::DeserializationFailure => f.write_str("JSON deserialization failure")?,
93            JsonErrorKind::TrailingValue => f.write_str("trailing top-level JSON value")?,
94            JsonErrorKind::InputBufferLimitExceeded(limit) => {
95                write!(f, "buffered JSON input exceeded limit of {limit} bytes")?
96            }
97            JsonErrorKind::EmptyPath => f.write_str("empty JSONPath expression")?,
98            JsonErrorKind::MissingRoot => f.write_str("JSONPath expression must start with `$`")?,
99            JsonErrorKind::UnsupportedJsonPath(feature) => {
100                write!(f, "unsupported JSONPath feature: {feature}")?
101            }
102            JsonErrorKind::UnsupportedRewrite(feature) => {
103                write!(f, "unsupported JSON rewrite operation: {feature}")?
104            }
105            JsonErrorKind::InvalidJsonPath(reason) => write!(f, "invalid JSONPath: {reason}")?,
106            JsonErrorKind::CaptureLimitExceeded(limit) => write!(
107                f,
108                "selected JSON value exceeded capture limit of {limit} bytes"
109            )?,
110        }
111
112        if let Some(offset) = self.offset {
113            write!(f, " at byte offset {offset}")?;
114        }
115        Ok(())
116    }
117}
118
119impl std::error::Error for JsonError {}