use std::num::TryFromIntError;
use simd_json::Buffers;
use crate::Tape;
fn expected(fields: &[&str]) -> String {
fields
.iter()
.map(|f| format!("`{f}`"))
.collect::<Vec<_>>()
.join(", ")
}
#[derive(Debug, thiserror::Error, PartialEq)]
pub enum Error {
#[error("json error: {0:?}")]
Json(simd_json::ErrorType),
#[error(transparent)]
Simd(#[from] simd_json::Error),
#[error("missing field: `{0}`")]
MissingField(&'static str),
#[error(
"unknown field `{unknown_field}`, expected one of {}",
expected(possible_field_names)
)]
UnknownField {
unknown_field: String,
possible_field_names: &'static [&'static str],
},
#[error("unnamed enum field `{0}` is not an array")]
FieldNotAnArray(&'static str),
#[error("unknwon enum variant `{0}`")]
UnknownEnumVariant(String),
#[error("invalid enum representation, needs to be either a string or an object")]
InvalidEnumRepresentation,
#[error("invalid struct representation, needs to be an object")]
InvalidStructRepresentation,
#[error("Unexpected e,nd of input")]
EOF,
#[error("Invalid integer number")]
InvalidNumber(#[from] TryFromIntError),
#[error("Custom error: {0}")]
Custom(String),
#[error("The universe is broken: {0}")]
BrokenUniverse(#[from] std::convert::Infallible),
}
impl Error {
pub fn custom<T: std::fmt::Display>(msg: T) -> Self {
Error::Custom(msg.to_string())
}
#[must_use]
pub const fn expected_string() -> Self {
Error::Json(simd_json::ErrorType::ExpectedString)
}
#[must_use]
pub const fn expected_map() -> Self {
Error::Json(simd_json::ErrorType::ExpectedMap)
}
#[must_use]
pub const fn expected_array() -> Self {
Error::Json(simd_json::ErrorType::ExpectedArray)
}
#[must_use]
pub const fn expected_float() -> Self {
Error::Json(simd_json::ErrorType::ExpectedFloat)
}
#[must_use]
pub fn expected_null() -> Self {
Error::Json(simd_json::ErrorType::ExpectedNull)
}
#[must_use]
pub fn expected_integer() -> Self {
Error::Json(simd_json::ErrorType::ExpectedInteger)
}
#[must_use]
pub fn expected_boolean() -> Self {
Error::Json(simd_json::ErrorType::ExpectedBoolean)
}
}
pub type Result<T> = std::result::Result<T, Error>;
pub trait Deserialize<'input> {
fn from_tape(tape: &mut Tape<'input>) -> Result<Self>
where
Self: Sized + 'input;
#[inline]
fn from_slice(json: &'input mut [u8]) -> Result<Self>
where
Self: Sized + 'input,
{
let tape = simd_json::to_tape(json)?;
let mut itr = tape.0.into_iter().peekable();
Self::from_tape(&mut itr)
}
#[inline]
fn from_slice_with_buffers(json: &'input mut [u8], buffers: &mut Buffers) -> Result<Self>
where
Self: Sized + 'input,
{
let tape = simd_json::Deserializer::from_slice_with_buffers(json, buffers)?.into_tape();
let mut itr = tape.0.into_iter().peekable();
Self::from_tape(&mut itr)
}
#[inline]
unsafe fn from_str(json: &'input mut str) -> Result<Self>
where
Self: Sized + 'input,
{
Self::from_slice(json.as_bytes_mut())
}
}