use std::fmt;
use crate::{JsonDecodeErrorKind, JsonDecodeStage, JsonTopLevelKind};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct JsonDecodeError {
pub kind: JsonDecodeErrorKind,
pub stage: JsonDecodeStage,
pub message: String,
pub expected_top_level: Option<JsonTopLevelKind>,
pub actual_top_level: Option<JsonTopLevelKind>,
pub line: Option<usize>,
pub column: Option<usize>,
pub input_bytes: Option<usize>,
pub max_input_bytes: Option<usize>,
}
impl JsonDecodeError {
#[inline]
pub(crate) fn input_too_large(actual_bytes: usize, max_bytes: usize) -> Self {
Self {
kind: JsonDecodeErrorKind::InputTooLarge,
stage: JsonDecodeStage::Normalize,
message: format!(
"JSON input is too large: {} bytes exceed configured limit {} bytes",
actual_bytes, max_bytes
),
expected_top_level: None,
actual_top_level: None,
line: None,
column: None,
input_bytes: Some(actual_bytes),
max_input_bytes: Some(max_bytes),
}
}
#[inline]
pub(crate) fn empty_input() -> Self {
Self {
kind: JsonDecodeErrorKind::EmptyInput,
stage: JsonDecodeStage::Normalize,
message: "JSON input is empty after normalization".to_string(),
expected_top_level: None,
actual_top_level: None,
line: None,
column: None,
input_bytes: None,
max_input_bytes: None,
}
}
#[inline]
pub(crate) fn invalid_json(error: serde_json::Error, input_bytes: Option<usize>) -> Self {
let line = error.line();
let column = error.column();
Self {
kind: JsonDecodeErrorKind::InvalidJson,
stage: JsonDecodeStage::Parse,
message: format!("Failed to parse JSON: {error}"),
expected_top_level: None,
actual_top_level: None,
line: (line > 0).then_some(line),
column: (column > 0).then_some(column),
input_bytes,
max_input_bytes: None,
}
}
#[inline]
pub(crate) fn unexpected_top_level(
expected: JsonTopLevelKind,
actual: JsonTopLevelKind,
) -> Self {
Self {
kind: JsonDecodeErrorKind::UnexpectedTopLevel,
stage: JsonDecodeStage::TopLevelCheck,
message: format!("Unexpected JSON top-level type: expected {expected}, got {actual}"),
expected_top_level: Some(expected),
actual_top_level: Some(actual),
line: None,
column: None,
input_bytes: None,
max_input_bytes: None,
}
}
#[inline]
pub(crate) fn deserialize(error: serde_json::Error, input_bytes: Option<usize>) -> Self {
let line = error.line();
let column = error.column();
Self {
kind: JsonDecodeErrorKind::Deserialize,
stage: JsonDecodeStage::Deserialize,
message: format!("Failed to deserialize JSON value: {error}"),
expected_top_level: None,
actual_top_level: None,
line: (line > 0).then_some(line),
column: (column > 0).then_some(column),
input_bytes,
max_input_bytes: None,
}
}
}
impl fmt::Display for JsonDecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
JsonDecodeErrorKind::InputTooLarge => f.write_str(&self.message),
JsonDecodeErrorKind::EmptyInput => f.write_str(&self.message),
JsonDecodeErrorKind::UnexpectedTopLevel => f.write_str(&self.message),
JsonDecodeErrorKind::InvalidJson | JsonDecodeErrorKind::Deserialize => {
match (self.line, self.column) {
(Some(line), Some(column)) => {
write!(f, "{} (line {}, column {})", self.message, line, column)
}
_ => f.write_str(&self.message),
}
}
}
}
}
impl std::error::Error for JsonDecodeError {}