use core::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Error {
Syntax {
offset: usize,
reason: &'static str,
},
TrailingContent {
offset: usize,
},
DuplicateMember {
name: String,
offset: usize,
},
StringNotScalar {
offset: usize,
reason: &'static str,
},
UnsafeInteger {
token: String,
},
NonIntegerNumber {
token: String,
},
NonFiniteNumber {
token: String,
},
TooDeep {
limit: usize,
offset: usize,
},
Canonicalization {
detail: String,
},
TooLarge {
len: usize,
limit: usize,
},
}
const RENDER_BUDGET: usize = 96;
fn clipped(value: &str) -> String {
let escaped = format!("{value:?}");
if escaped.len() <= RENDER_BUDGET {
return escaped;
}
let end = (0..=RENDER_BUDGET)
.rev()
.find(|i| escaped.is_char_boundary(*i))
.unwrap_or(0);
format!(
"{}... [{} bytes elided]",
&escaped[..end],
value.len().saturating_sub(end)
)
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Syntax { offset, reason } => {
write!(f, "invalid JSON at byte {offset}: {reason}")
}
Self::TrailingContent { offset } => {
write!(f, "trailing content after the JSON value at byte {offset}")
}
Self::DuplicateMember { name, offset } => {
write!(
f,
"duplicate object member {} at byte {offset}",
clipped(name)
)
}
Self::StringNotScalar { offset, reason } => write!(
f,
"JSON string is not a sequence of Unicode scalar values at byte {offset}: {reason}"
),
Self::UnsafeInteger { token } => {
write!(
f,
"integer outside the I-JSON safe range: {}",
clipped(token)
)
}
Self::NonIntegerNumber { token } => {
write!(
f,
"non-integer number outside the integers-only profile: {}",
clipped(token)
)
}
Self::NonFiniteNumber { token } => {
write!(
f,
"number is not a finite IEEE-754 double: {}",
clipped(token)
)
}
Self::TooDeep { limit, offset } => {
write!(
f,
"JSON nesting exceeds the maximum depth {limit} at byte {offset}"
)
}
Self::TooLarge { len, limit } => {
write!(f, "JSON input of {len} bytes exceeds the maximum {limit}")
}
Self::Canonicalization { detail } => {
write!(
f,
"canonicalization of an admitted document failed: {detail}"
)
}
}
}
}
impl std::error::Error for Error {}