1use std::{
14 fmt,
15 sync::Arc,
16};
17
18use crate::{
19 JsonDecodeErrorKind,
20 JsonDecodeStage,
21 JsonTopLevelKind,
22};
23
24#[non_exhaustive]
29#[derive(Debug, Clone)]
30pub struct JsonDecodeError {
31 pub kind: JsonDecodeErrorKind,
36 pub stage: JsonDecodeStage,
38 pub message: String,
43 pub expected_top_level: Option<JsonTopLevelKind>,
48 pub actual_top_level: Option<JsonTopLevelKind>,
53 pub line: Option<usize>,
58 pub column: Option<usize>,
63 pub input_bytes: Option<usize>,
65 pub max_input_bytes: Option<usize>,
67 source: Option<Arc<serde_json::Error>>,
69}
70
71impl JsonDecodeError {
72 #[inline]
75 pub(crate) fn input_too_large(actual_bytes: usize, max_bytes: usize) -> Self {
76 Self {
77 kind: JsonDecodeErrorKind::InputTooLarge,
78 stage: JsonDecodeStage::Normalize,
79 message: format!(
80 "JSON input is too large: {} bytes exceed configured limit {} bytes",
81 actual_bytes, max_bytes
82 ),
83 expected_top_level: None,
84 actual_top_level: None,
85 line: None,
86 column: None,
87 input_bytes: Some(actual_bytes),
88 max_input_bytes: Some(max_bytes),
89 source: None,
90 }
91 }
92
93 #[inline]
96 pub(crate) fn empty_input() -> Self {
97 Self {
98 kind: JsonDecodeErrorKind::EmptyInput,
99 stage: JsonDecodeStage::Normalize,
100 message: "JSON input is empty after normalization".to_string(),
101 expected_top_level: None,
102 actual_top_level: None,
103 line: None,
104 column: None,
105 input_bytes: None,
106 max_input_bytes: None,
107 source: None,
108 }
109 }
110
111 #[inline]
114 pub(crate) fn invalid_json(error: serde_json::Error, input_bytes: Option<usize>) -> Self {
115 let line = error.line();
116 let column = error.column();
117 let message = format!("Failed to parse JSON: {error}");
118 Self {
119 kind: JsonDecodeErrorKind::InvalidJson,
120 stage: JsonDecodeStage::Parse,
121 message,
122 expected_top_level: None,
123 actual_top_level: None,
124 line: (line > 0).then_some(line),
125 column: (column > 0).then_some(column),
126 input_bytes,
127 max_input_bytes: None,
128 source: Some(Arc::new(error)),
129 }
130 }
131
132 #[inline]
135 pub(crate) fn unexpected_top_level(expected: JsonTopLevelKind, actual: JsonTopLevelKind) -> Self {
136 Self {
137 kind: JsonDecodeErrorKind::UnexpectedTopLevel,
138 stage: JsonDecodeStage::TopLevelCheck,
139 message: format!("Unexpected JSON top-level type: expected {expected}, got {actual}"),
140 expected_top_level: Some(expected),
141 actual_top_level: Some(actual),
142 line: None,
143 column: None,
144 input_bytes: None,
145 max_input_bytes: None,
146 source: None,
147 }
148 }
149
150 #[inline]
153 pub(crate) fn deserialize(error: serde_json::Error, input_bytes: Option<usize>) -> Self {
154 let line = error.line();
155 let column = error.column();
156 let message = format!("Failed to deserialize JSON value: {error}");
157 Self {
158 kind: JsonDecodeErrorKind::Deserialize,
159 stage: JsonDecodeStage::Deserialize,
160 message,
161 expected_top_level: None,
162 actual_top_level: None,
163 line: (line > 0).then_some(line),
164 column: (column > 0).then_some(column),
165 input_bytes,
166 max_input_bytes: None,
167 source: Some(Arc::new(error)),
168 }
169 }
170}
171
172impl PartialEq for JsonDecodeError {
173 fn eq(&self, other: &Self) -> bool {
174 self.kind == other.kind
175 && self.stage == other.stage
176 && self.message == other.message
177 && self.expected_top_level == other.expected_top_level
178 && self.actual_top_level == other.actual_top_level
179 && self.line == other.line
180 && self.column == other.column
181 && self.input_bytes == other.input_bytes
182 && self.max_input_bytes == other.max_input_bytes
183 }
184}
185
186impl Eq for JsonDecodeError {}
187
188impl fmt::Display for JsonDecodeError {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 match self.kind {
191 JsonDecodeErrorKind::InputTooLarge => f.write_str(&self.message),
192 JsonDecodeErrorKind::EmptyInput => f.write_str(&self.message),
193 JsonDecodeErrorKind::UnexpectedTopLevel => f.write_str(&self.message),
194 JsonDecodeErrorKind::InvalidJson | JsonDecodeErrorKind::Deserialize => match (self.line, self.column) {
195 (Some(line), Some(column)) => {
196 write!(f, "{} (line {}, column {})", self.message, line, column)
197 }
198 _ => f.write_str(&self.message),
199 },
200 }
201 }
202}
203
204impl std::error::Error for JsonDecodeError {
205 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
206 self.source
207 .as_deref()
208 .map(|error| error as &(dyn std::error::Error + 'static))
209 }
210}