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