use std::{borrow::Cow, fmt::Display, iter::Peekable};
use serde::de::IntoDeserializer;
use crate::token::{self, TType};
#[derive(Debug)]
pub enum Error {
DeserializeError(String),
SyntaxError(String),
UnexpectedEndOfInput,
TrailingCharacters,
}
pub type Result<T> = std::result::Result<T, Error>;
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::DeserializeError(msg) | Error::SyntaxError(msg) => f.write_str(msg),
Error::UnexpectedEndOfInput => f.write_str("unexpected end of input"),
Error::TrailingCharacters => f.write_str("unexpected trailing non-whitespace"),
}
}
}
impl std::error::Error for Error {}
impl serde::de::Error for Error {
fn custom<T>(msg: T) -> Self
where
T: Display,
{
Error::DeserializeError(msg.to_string())
}
}
impl From<token::Error> for Error {
fn from(value: token::Error) -> Self {
Self::SyntaxError(format!("{value:#}"))
}
}
pub fn from_str<'a, T: serde::de::Deserialize<'a>>(input: &'a str) -> Result<T> {
let mut de = Deserializer::from_str(input);
let value = T::deserialize(&mut de)?;
match de.tokens.next() {
None => Ok(value),
Some(_) => Err(Error::TrailingCharacters),
}
}
pub struct Deserializer<'de> {
tokens: Peekable<token::Scanner<'de>>,
value_objects: bool,
}
macro_rules! invalid_eof {
() => {
Err(Error::UnexpectedEndOfInput)
};
}
macro_rules! invalid_syntax {
($token:ident, $expected:expr) => {
Err(Error::SyntaxError(format!(
"Unexpected token '{}' [line: {}, column: {}]; expected {}",
$token.ttype, $token.line, $token.column, $expected
)))
};
}
macro_rules! expect_next {
($de:expr, |$t:ident| { $( $pattern:pat $(if $condition:expr)? => $handler:expr ),* $(,)? }) => {
match ($de).tokens.next() {
None => return invalid_eof!(),
Some(Err(e)) => return Err(e.into()),
Some(Ok($t)) => match $t.ttype {
$(
$pattern $(if $condition)? => { $handler }
),*
},
}
};
($de:expr, $expected:expr, { $( $pattern:pat $(if $condition:expr)? => $handler:expr ),* $(,)? }) => {
expect_next!($de, |t| {
$(
$pattern $(if $condition)? => $handler
),* ,
_ => return invalid_syntax!(t, $expected),
})
};
}
macro_rules! expect_peek {
($deserializer:expr, |$t:ident| { $($pattern:pat => $handler:expr),* $(,)? }) => {
match $deserializer.tokens.peek() {
None => {
let _ = $deserializer.tokens.next();
return invalid_eof!();
}
Some(Err(_)) => {
return Err($deserializer.tokens.next().unwrap().err().unwrap().into());
}
Some(Ok($t)) => match &$t.ttype {
$( $pattern => { $handler } ),*
},
}
};
($deserializer:expr, $expected:expr, { $($pattern:pat => $handler:expr),* $(,)? }) => {
expect_peek!($deserializer, |t| {
$( $pattern => $handler ),* ,
_ => return invalid_syntax!(t, $expected),
})
};
}
macro_rules! deserialize_int {
($expected:literal, $deserialize_method:ident, $visit_method:ident) => {
fn $deserialize_method<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, $expected, {
TType::Int(lexem) => match lexem.parse() {
Err(e) => Err(Error::DeserializeError(format!("not {}: {e}", $expected))),
Ok(value) => visitor.$visit_method(value),
},
})
}
};
}
macro_rules! deserialize_string {
($expected:expr,
$deserialize_method:ident,
|$visitor:ident, $lexem:ident|
no_escapes: $visit_string:expr,
with_escapes: $visit_string_esc:expr,
) => {
fn $deserialize_method<V>(self, $visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, $expected, {
TType::String($lexem, esc) => {
let $lexem = $lexem.unquoted();
if esc {
$visit_string_esc
} else {
$visit_string
}
},
TType::Ident($lexem) => {
$visit_string
},
TType::LeftBracket => self.deserialize_opened_bytes($visitor),
})
}
};
}
macro_rules! deserialize_float {
($expected:literal, $deserialize_method:ident, $visit_method:ident) => {
fn $deserialize_method<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, $expected, {
TType::Int(lexem) | TType::Float(lexem) => match lexem.parse() {
Err(e) => Err(Error::DeserializeError(format!("not {}: {e}", $expected))),
Ok(value) => visitor.$visit_method(value),
}
})
}
};
}
const EXPECTED_BYTE: &str = "an unsigned integer in the range of 0..=255";
impl<'de> Deserializer<'de> {
#[allow(clippy::should_implement_trait)]
pub fn from_str(input: &'de str) -> Self {
Deserializer {
tokens: token::parse(input).peekable(),
value_objects: true,
}
}
pub fn with_value_objects(mut self, value_objects: bool) -> Self {
self.value_objects = value_objects;
self
}
fn deserialize_properties<V>(
&mut self,
visitor: V,
fields: Option<usize>,
) -> std::result::Result<V::Value, Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "an opening paranthesis ('(') or curly brace ('{')", {
TType::LeftParen => {
visitor.visit_seq(SeqAccess::new(self, fields, SeqEnd::Parens))
},
TType::LeftCurly => {
let value = visitor.visit_map(MapAccess::new(self))?;
expect_next!(self, "a closing curly brace ('}')", {
TType::RightCurly => Ok(value),
})
}
})
}
fn deserialize_opened_bytes<V>(&mut self, visitor: V) -> std::result::Result<V::Value, Error>
where
V: serde::de::Visitor<'de>,
{
enum NextPossible {
ElemOrEnd,
SepOrEnd,
}
let mut state = NextPossible::ElemOrEnd;
let mut buf = Vec::<u8>::new();
loop {
match state {
NextPossible::ElemOrEnd => {
expect_next!(self, format_args!("{EXPECTED_BYTE} or a closing bracket (']')"), {
TType::Int(lexem) => match lexem.parse::<u8>() {
Err(e) => return Err(Error::DeserializeError(format!(
"not {EXPECTED_BYTE}: {e}"
))),
Ok(value) => {
buf.push(value);
state = NextPossible::SepOrEnd;
}
},
TType::RightBracket => break,
})
}
NextPossible::SepOrEnd => {
expect_next!(self, "a comma (',') or a closing bracket (']')", {
TType::Comma => {
state = NextPossible::ElemOrEnd;
},
TType::RightBracket => break,
})
}
}
}
visitor.visit_byte_buf(buf)
}
}
impl<'de> serde::de::Deserializer<'de> for &mut Deserializer<'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_peek!(self, "null, a boolean, a number, a string, a map, or a list", {
TType::LeftCurly => self.deserialize_map(visitor),
TType::LeftBracket => self.deserialize_seq(visitor),
TType::True | TType::False => self.deserialize_bool(visitor),
TType::Null => self.deserialize_option(visitor),
TType::Ident(lexem) => {
let lexem = lexem.clone();
let _ = self.tokens.next();
expect_peek!(self, |t| {
TType::LeftParen | TType::LeftCurly => if self.value_objects {
visitor.visit_enum(DeserializeAnyEnumDeserializer::new(lexem.into_str(), self))
} else {
self.deserialize_properties(visitor, None)
},
_ => invalid_syntax!(t, "an opening parenthesis ('(') or curly brace ('{')"),
})
},
TType::String(_, false) => self.deserialize_str(visitor),
TType::String(_, true) => self.deserialize_string(visitor),
TType::Int(lexem) => if lexem.starts_with('-') {
self.deserialize_i64(visitor)
} else {
self.deserialize_u64(visitor)
},
TType::Float(_) => self.deserialize_f64(visitor),
})
}
fn deserialize_ignored_any<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
fast_ignore::deserialize_ignored_any(self)?;
visitor.visit_unit()
}
fn deserialize_bool<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "a boolean", {
TType::True => visitor.visit_bool(true),
TType::False => visitor.visit_bool(false),
})
}
deserialize_int!(
"a signed integer in the range of -128..=127",
deserialize_i8,
visit_i8
);
deserialize_int!(
"a signed integer in the range of -32768..=32767",
deserialize_i16,
visit_i16
);
deserialize_int!(
"a signed integer in the range of -2147483648..=2147483647",
deserialize_i32,
visit_i32
);
deserialize_int!(
"a signed integer in the range of -9223372036854775808..=9223372036854775807",
deserialize_i64,
visit_i64
);
deserialize_int!(
"an unsigned integer in the range of 0..=255",
deserialize_u8,
visit_u8
);
deserialize_int!(
"an unsigned integer in the range of 0..=65535",
deserialize_u16,
visit_u16
);
deserialize_int!(
"an unsigned integer in the range of 0..=4294967295",
deserialize_u32,
visit_u32
);
deserialize_int!(
"an unsigned integer in the range of 0..=18446744073709551615",
deserialize_u64,
visit_u64
);
deserialize_float!(
"a single precision floating point number",
deserialize_f32,
visit_f32
);
deserialize_float!(
"a double precision floating point number",
deserialize_f64,
visit_f64
);
deserialize_string!("a one character string", deserialize_char, |visitor, lexem|
no_escapes: match lexem.single_char_raw() {
None => Err(Error::DeserializeError("not a one character string".to_string())),
Some(c) => visitor.visit_char(c)
},
with_escapes: match lexem.single_char_unescaped() {
None => Err(Error::DeserializeError("not a one character string".to_string())),
Some(c) => visitor.visit_char(c)
},
);
deserialize_string!("a string", deserialize_str, |visitor, lexem|
no_escapes: visitor.visit_borrowed_str(lexem.into_str()),
with_escapes: visitor.visit_string(lexem.unescaped()),
);
deserialize_string!("a string", deserialize_string, |visitor, lexem|
no_escapes: visitor.visit_string(lexem.to_string()),
with_escapes: visitor.visit_string(lexem.unescaped()),
);
fn deserialize_bytes<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "a string or a list of integers in the range of 0..=255", {
TType::String(lexem, false) => visitor.visit_borrowed_bytes(lexem.unquoted().into_str().as_bytes()),
TType::String(lexem, true) => visitor.visit_byte_buf(lexem.unquoted().unescaped().into_bytes()),
})
}
fn deserialize_byte_buf<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_bytes(visitor)
}
fn deserialize_option<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_peek!(self, "a `null` or a value", {
TType::Null => {
let _ = self.tokens.next();
visitor.visit_none()
},
TType::True => visitor.visit_some(self),
TType::False => visitor.visit_some(self),
TType::LeftCurly => visitor.visit_some(self),
TType::LeftBracket => visitor.visit_some(self),
TType::Ident(_) => visitor.visit_some(self),
TType::String(_, _) => visitor.visit_some(self),
TType::Int(_) => visitor.visit_some(self),
TType::Float(_) => visitor.visit_some(self),
})
}
fn deserialize_unit<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "a `null`", { TType::Null => visitor.visit_unit() })
}
fn deserialize_unit_struct<V>(
self,
name: &'static str,
visitor: V,
) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "an identifier followed by '()' or '{}'", {
TType::Ident(lexem) => {
if &*lexem == name {
expect_next!(self, "expected an opening parenthesis ('(') or opening curly brace ('{')", {
TType::LeftParen => expect_next!(self, "expected a closig parenthesis (')')", {
TType::RightParen => visitor.visit_unit(),
}),
TType::LeftCurly => expect_next!(self, "expected a closig brace ('}')", {
TType::RightCurly => visitor.visit_unit(),
}),
})
} else {
Err(serde::de::Error::custom(format!("invalid name, expected '{name}'")))
}
}
})
}
fn deserialize_newtype_struct<V>(
self,
name: &'static str,
visitor: V,
) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_peek!(self, "an identifier or value", {
TType::Ident(lexem) => {
if &**lexem == name {
let _ = self.tokens.next();
expect_next!(self, "an opening parenthesis ('(')", { TType::LeftParen => {} });
let value = visitor.visit_newtype_struct(&mut *self)?;
expect_next!(self, "a closing parenthesis (')')", { TType::RightParen => {} });
Ok(value)
} else {
Err(serde::de::Error::custom(format!("invalid identifier; expected {name}, but got {}", &**lexem)))
}
},
TType::LeftCurly
| TType::LeftBracket
| TType::True
| TType::False
| TType::Null
| TType::String(_, _)
| TType::Int(_)
| TType::Float(_) => visitor.visit_newtype_struct(self),
})
}
fn deserialize_seq<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "an opening bracket ('[')", {
TType::LeftBracket => visitor.visit_seq(SeqAccess::new(self, None, SeqEnd::Brackets))
})
}
fn deserialize_tuple<V>(
self,
len: usize,
visitor: V,
) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "an opening bracket ('[')", {
TType::LeftBracket => visitor.visit_seq(SeqAccess::new(self, Some(len), SeqEnd::Brackets))
})
}
fn deserialize_tuple_struct<V>(
self,
name: &'static str,
len: usize,
visitor: V,
) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "an identifier", {
TType::Ident(lexem) => {
if &*lexem == name {
expect_next!(self, "an opening parenthesis ('(')", {
TType::LeftParen => visitor.visit_seq(SeqAccess::new(self, Some(len), SeqEnd::Parens))
})
} else {
Err(serde::de::Error::custom(format!("invalid identifier; expected {name}, but got {}", &*lexem)))
}
}
})
}
fn deserialize_map<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "an opening curly brace ('{')", {
TType::LeftCurly => {
let value = visitor.visit_map(MapAccess::new(self))?;
expect_next!(self, "a closing curly brace ('}')", {
TType::RightCurly => {
Ok(value)
},
})
}
})
}
fn deserialize_struct<V>(
self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_peek!(self, format_args!("the identifier '{name}' or an opening curly brace ('{{')"), {
TType::Ident(lexem) => {
if &**lexem == name {
let _ = self.tokens.next();
self.deserialize_properties(visitor, Some(fields.len()))
} else {
Err(serde::de::Error::custom(format!("invalid name, expected '{name}'")))
}
},
TType::LeftCurly => self.deserialize_properties(visitor, None),
})
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_peek!(self, "a string", {
TType::String(lexem, has_escapes) => {
let name = if *has_escapes {
Cow::Owned(lexem.unquoted().unescaped())
} else {
Cow::Borrowed(lexem.unquoted().into_str())
};
let _ = self.tokens.next(); visitor.visit_enum(EmptyVariantOnly::new(name))
},
TType::Ident(_) => {
visitor.visit_enum(EnumDeserializer::new(self))
}
})
}
fn deserialize_identifier<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self, "an identifier", {
TType::Ident(lexem) => visitor.visit_borrowed_str(lexem.into_str()),
})
}
}
struct EmptyVariantOnly<'a> {
name: Cow<'a, str>,
}
impl<'a> EmptyVariantOnly<'a> {
fn new(name: Cow<'a, str>) -> Self {
Self { name }
}
}
macro_rules! expected_empty_variant {
($unexpected:literal) => {
Err(Error::DeserializeError(format!(
"invalid type: {}, expected unit or empty tuple or empty struct variant",
$unexpected
)))
};
}
impl<'de> serde::de::EnumAccess<'de> for EmptyVariantOnly<'de> {
type Error = Error;
type Variant = EmptyVariantOnlyAccess;
fn variant_seed<V>(self, seed: V) -> std::result::Result<(V::Value, Self::Variant), Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
Ok((
seed.deserialize(IntoDeserializer::<'_, Self::Error>::into_deserializer(
self.name,
))?,
EmptyVariantOnlyAccess,
))
}
}
struct EmptyVariantOnlyAccess;
impl<'de> serde::de::VariantAccess<'de> for EmptyVariantOnlyAccess {
type Error = Error;
fn unit_variant(self) -> std::result::Result<(), Self::Error> {
Ok(())
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
if len == 0 {
visitor.visit_seq(Vec::<()>::new().into_deserializer())
} else {
expected_empty_variant!("non-empty tuple variant")
}
}
fn newtype_variant_seed<T>(self, _seed: T) -> std::result::Result<T::Value, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
expected_empty_variant!("newtype variant")
}
fn struct_variant<V>(
self,
fields: &'static [&'static str],
visitor: V,
) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
if fields.is_empty() {
visitor.visit_unit()
} else {
expected_empty_variant!("struct variant")
}
}
}
struct DeserializeAnyEnumDeserializer<'a, 'de> {
name: &'de str,
de: &'a mut Deserializer<'de>,
}
impl<'a, 'de> DeserializeAnyEnumDeserializer<'a, 'de> {
fn new(name: &'de str, de: &'a mut Deserializer<'de>) -> Self {
Self { name, de }
}
}
impl<'de> serde::de::EnumAccess<'de> for DeserializeAnyEnumDeserializer<'_, 'de> {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> std::result::Result<(V::Value, Self::Variant), Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
seed.deserialize(self.name.into_deserializer())
.map(|name| (name, self))
}
}
impl<'de> serde::de::VariantAccess<'de> for DeserializeAnyEnumDeserializer<'_, 'de> {
type Error = Error;
fn unit_variant(self) -> std::result::Result<(), Self::Error> {
Err(Error::DeserializeError("not a unit variant".to_string()))
}
fn newtype_variant_seed<T>(self, seed: T) -> std::result::Result<T::Value, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
seed.deserialize(DeserializeObjectDeserializer(self.de))
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
if len == 1 {
visitor.visit_seq(DeserializeAnyEnumSeqAccess::new(self.de))
} else {
Err(Error::DeserializeError("not a newtype variant".to_string()))
}
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
visitor: V,
) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.de.deserialize_properties(visitor, None)
}
}
struct DeserializeAnyEnumSeqAccess<'a, 'de>(Option<&'a mut Deserializer<'de>>);
impl<'a, 'de> DeserializeAnyEnumSeqAccess<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self {
Self(Some(de))
}
}
impl<'de> serde::de::SeqAccess<'de> for DeserializeAnyEnumSeqAccess<'_, 'de> {
type Error = Error;
fn next_element_seed<T>(
&mut self,
seed: T,
) -> std::result::Result<Option<T::Value>, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
match self.0.take() {
Some(de) => seed
.deserialize(DeserializeObjectDeserializer(de))
.map(Some),
None => Ok(None),
}
}
fn size_hint(&self) -> Option<usize> {
Some(if self.0.is_none() { 0 } else { 1 })
}
}
struct DeserializeObjectDeserializer<'a, 'de>(&'a mut Deserializer<'de>);
impl<'de> serde::de::Deserializer<'de> for DeserializeObjectDeserializer<'_, 'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.0.deserialize_properties(visitor, None)
}
serde::forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
struct EnumDeserializer<'a, 'de> {
de: &'a mut Deserializer<'de>,
}
impl<'a, 'de> EnumDeserializer<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self {
Self { de }
}
}
impl<'de> serde::de::EnumAccess<'de> for EnumDeserializer<'_, 'de> {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> std::result::Result<(V::Value, Self::Variant), Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
Ok((seed.deserialize(&mut *self.de)?, self))
}
}
impl<'de> serde::de::VariantAccess<'de> for EnumDeserializer<'_, 'de> {
type Error = Error;
fn unit_variant(self) -> std::result::Result<(), Self::Error> {
expect_next!(self.de, "a \"()\" or \"{}\"", {
TType::LeftCurly => expect_next!(self.de, "a closing curly brace ('}')", {
TType::RightCurly => Ok(()),
}),
TType::LeftParen => expect_next!(self.de, "a closing paranthesis (')')", {
TType::RightParen => Ok(()),
})
})
}
fn newtype_variant_seed<T>(self, seed: T) -> std::result::Result<T::Value, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
expect_next!(self.de, "an opening parenthesis ('(')", {
TType::LeftParen => {
let value = seed.deserialize(&mut *self.de)?;
expect_next!(self.de, "a closing parenthesis (')')", {
TType::RightParen => Ok(value),
})
}
})
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
expect_next!(self.de, "an opening parenthesis ('(') or curly brace ('{')", {
TType::LeftParen => {
let value = visitor.visit_seq(SeqAccess::new(
&mut *self.de,
Some(len),
SeqEnd::Parens,
))?;
if len == 0 {
expect_next!(self.de, "a closing parenthesis (')')", {
TType::RightParen => Ok(value)
})
} else {
Ok(value)
}
},
TType::LeftCurly if len == 0 => {
visitor.visit_seq(Vec::<()>::new().into_deserializer())
.and_then(|value| expect_next!(self.de, "a closing curly brace ('}')", {
TType::RightCurly => Ok(value)
}))
}
})
}
fn struct_variant<V>(
self,
fields: &'static [&'static str],
visitor: V,
) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.de.deserialize_properties(visitor, Some(fields.len()))
}
}
#[derive(Clone, Copy)]
enum SeqEnd {
Brackets,
Parens,
}
struct SeqAccess<'a, 'de> {
de: &'a mut Deserializer<'de>,
remaining: Option<usize>,
end_token: SeqEnd,
end_consumed: bool,
}
impl<'a, 'de> SeqAccess<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>, len: Option<usize>, end_token: SeqEnd) -> Self {
Self {
de,
remaining: len,
end_token,
end_consumed: false,
}
}
fn expect_end(&mut self) -> Result<()> {
let mut comma_allowed = true;
loop {
match self.de.tokens.next() {
None => return invalid_eof!(),
Some(Err(e)) => return Err(e.into()),
Some(Ok(t)) => match (comma_allowed, &t.ttype, self.end_token) {
(_, TType::RightBracket, SeqEnd::Brackets)
| (_, TType::RightParen, SeqEnd::Parens) => {
self.end_consumed = true;
return Ok(());
}
(true, TType::Comma, _) => {
comma_allowed = false;
}
_ => {
return invalid_syntax!(
t,
match self.end_token {
SeqEnd::Brackets => "a closing bracket (']')",
SeqEnd::Parens => "a closing paranthesis (')')",
}
);
}
},
}
}
}
}
impl<'de> serde::de::SeqAccess<'de> for SeqAccess<'_, 'de> {
type Error = Error;
fn next_element_seed<T>(
&mut self,
seed: T,
) -> std::result::Result<Option<T::Value>, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
if self.end_consumed {
if let Some(remaining) = self.remaining.as_mut() {
if *remaining == 0 {
panic!("asked for too many elements");
}
*remaining -= 1;
Ok(None)
} else {
panic!("not expected to be called beyond of unrestricted sequence");
}
} else {
match self.de.tokens.peek() {
None => invalid_eof!(),
Some(Err(_)) => Err(self.de.tokens.next().unwrap().err().unwrap().into()),
Some(Ok(t)) => match (&t.ttype, self.end_token) {
(TType::RightBracket, SeqEnd::Brackets)
| (TType::RightParen, SeqEnd::Parens) => {
let _ = self.de.tokens.next();
self.end_consumed = true;
if let Some(remaining) = self.remaining.as_mut() {
if *remaining > 0 {
*remaining -= 1;
Ok(None)
} else {
panic!("asked for too many elements");
}
} else {
Ok(None)
}
}
(TType::Colon, _) => {
invalid_syntax!(
t,
match self.end_token {
SeqEnd::Brackets =>
"a value, a comma (','), or a closing bracket (']')",
SeqEnd::Parens =>
"a value, a comma (','), or a closing parenthesis (')')",
}
)
}
_ => {
if self
.remaining
.map(|remaining| remaining == 0)
.unwrap_or(false)
{
self.expect_end()?;
Ok(None)
} else {
let value = seed.deserialize(&mut *self.de).map(Some);
if let Some(remaining) = self.remaining.as_mut() {
*remaining -= 1;
if *remaining == 0 {
self.expect_end()?;
return value;
}
}
if self
.de
.tokens
.peek()
.and_then(|r| {
r.as_ref().map(|t| matches!(&t.ttype, TType::Comma)).ok()
})
.unwrap_or(false)
{
let _ = self.de.tokens.next();
}
value
}
}
},
}
}
}
}
struct MapAccess<'a, 'de> {
de: &'a mut Deserializer<'de>,
}
impl<'a, 'de> MapAccess<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self {
Self { de }
}
}
impl<'de> serde::de::MapAccess<'de> for MapAccess<'_, 'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> std::result::Result<Option<K::Value>, Self::Error>
where
K: serde::de::DeserializeSeed<'de>,
{
if matches!(
self.de.tokens.peek(),
Some(Ok(token::Token {
ttype: TType::RightCurly,
..
}))
) {
Ok(None)
} else {
let key = seed.deserialize(&mut *self.de).map(Some)?;
expect_next!(self.de, "a colon (':')", {
TType::Colon => Ok(key),
})
}
}
fn next_value_seed<V>(&mut self, seed: V) -> std::result::Result<V::Value, Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
let value = seed.deserialize(&mut *self.de)?;
if matches!(
self.de.tokens.peek(),
Some(Ok(token::Token {
ttype: TType::Comma,
..
}))
) {
let _ = self.de.tokens.next();
}
Ok(value)
}
}
mod fast_ignore {
use super::*;
pub fn deserialize_ignored_any<'de>(
de: &mut Deserializer<'de>,
) -> std::result::Result<(), Error> {
let mut expect_next;
let mut expect_stack = ExpectStack::default();
macro_rules! expect_stack_push {
($expect:path) => {{
expect_next = $expect;
expect_stack.push(expect_next);
}};
}
expect_next!(de, "null, a boolean, a number, a string, a map, or a list", {
TType::Float(_) | TType::Int(_) | TType::String(_, _) | TType::Null | TType::True | TType::False => return Ok(()),
TType::LeftCurly => expect_stack_push!(Expect::DataMapKey),
TType::LeftBracket => expect_stack_push!(Expect::ListValue),
TType::Ident(_) => {
expect_next!(de, |t| {
TType::LeftCurly => expect_stack_push!(Expect::KwMapKey),
TType::LeftParen => expect_stack_push!(Expect::TupleValue),
_ => return invalid_syntax!(t, "an opening parenthesis ('(') or curly brace ('{')"),
})
},
});
'top: loop {
macro_rules! expect_stack_pop {
() => {{
expect_stack.pop();
if let Some(op) = expect_stack.last() {
expect_next = op;
} else {
break 'top;
}
}};
}
macro_rules! expect_stack_replace_and_push {
($replacement:expr, $expect_next:path) => {{
expect_stack.replace_last($replacement);
expect_next = $expect_next;
expect_stack.push(expect_next);
}};
}
macro_rules! expect_value {
(@__ { $($end:tt)* } $err_msg:literal $expect_next:path { $($after_ident_match:tt)* }) => {
expect_next!(de, $err_msg, {
$($end)*
TType::Float(_) | TType::Int(_) | TType::String(_, _) | TType::Null | TType::True | TType::False => {
expect_next = $expect_next;
},
TType::LeftCurly => expect_stack_replace_and_push!($expect_next, Expect::DataMapKey),
TType::LeftBracket => expect_stack_replace_and_push!($expect_next, Expect::ListValue),
TType::Ident(_) => {
expect_next!(de, |t| {
TType::LeftCurly => expect_stack_replace_and_push!($expect_next, Expect::KwMapKey),
TType::LeftParen => expect_stack_replace_and_push!($expect_next, Expect::TupleValue),
$($after_ident_match)*
_ => return invalid_syntax!(t, "an opening parenthesis ('(') or curly brace ('{')"),
})
},
})
};
(
// the end token pattern
end: $end:pat,
// error to be shown if neither end not a value is found
err: $err_msg:literal,
// the state to transition next when a value is encountered
next: $expect_next:path
// additional match arm to optionally handle a
// token following an identifier (unless it's a
// curly or a paren)
$(, next_after_ident: $($after_ident:tt)+ )?
) => {
expect_value!(@__ { $end => expect_stack_pop!(), } $err_msg $expect_next {$($($after_ident)*)?})
};
(
no_end,
err: $err_msg:literal,
next: $expect_next:path
) => {
expect_value!(@__ {} $err_msg $expect_next {})
};
}
macro_rules! expect_ident {
(end: $end:pat, err: $err_msg:literal, next: $expect_next:path) => {
expect_next!(de, $err_msg, {
$end => expect_stack_pop!(),
TType::Ident(_) => { expect_next = $expect_next; },
})
}
}
macro_rules! expect_comma {
(end: $end:pat, err: $err_msg:literal, next: $expect_next:path) => {
expect_next!(de, $err_msg, {
$end => expect_stack_pop!(),
TType::Comma => { expect_next = $expect_next; },
})
};
}
match expect_next {
Expect::ListValue => expect_value!(
end: TType::RightBracket,
err: "a value or a closing bracket (']')",
next: Expect::ListComma
),
Expect::ListComma => expect_comma!(
end: TType::RightBracket,
err: "a comma or a closing bracket (']')",
next: Expect::ListValue
),
Expect::TupleValue => expect_value!(
end: TType::RightParen,
err: "a value or a closing parenthesis (')')",
next: Expect::TupleComma
),
Expect::TupleComma => expect_comma!(
end: TType::RightParen,
err: "a comma or a closing parenthesis (')')",
next: Expect::TupleValue
),
Expect::DataMapKey => expect_value!(
end: TType::RightCurly,
err: "a value or a closing curly brace ('}')",
next: Expect::DataMapColon,
next_after_ident: TType::Colon => expect_next = Expect::DataMapValue,
),
Expect::DataMapColon => expect_next!(de, "a colon", {
TType::Colon => expect_next = Expect::DataMapValue,
}),
Expect::DataMapValue => expect_value!(
no_end,
err: "a value",
next: Expect::DataMapComma
),
Expect::DataMapComma => expect_comma!(
end: TType::RightCurly,
err: "a comma or a closing brace ('}')",
next: Expect::DataMapKey
),
Expect::KwMapKey => expect_ident!(
end: TType::RightCurly,
err: "an identifier or a closing curly brace ('}')",
next: Expect::KwMapColon
),
Expect::KwMapColon => expect_next!(de, "a colon", {
TType::Colon => expect_next = Expect::KwMapValue,
}),
Expect::KwMapValue => expect_value!(
no_end,
err: "a value",
next: Expect::KwMapComma
),
Expect::KwMapComma => expect_comma!(
end: TType::RightCurly,
err: "a comma or a closing brace ('}')",
next: Expect::KwMapKey
),
}
}
Ok(())
}
macro_rules! expect_enum {
(@__
$(#[$tm:meta])*
$type_name:ident
$values_name:ident
$bitwidth_name:ident
{ $( $prepared_variant:tt )* }
{ $( $prepared_value:tt )* }
{ $count:expr }
) => {
$(#[$tm])*
#[derive(Clone, Copy)]
enum $type_name {
$( $prepared_variant )*
}
const $values_name: [$type_name; $count] = [
$( $prepared_value )*
];
const $bitwidth_name: usize = ((($count as usize).ilog2() + 1) as usize).next_power_of_two();
};
(@__
$(#[$tm:meta])*
$type_name:ident
$values_name:ident
$bitwidth_name:ident
{ $( $prepared_variant:tt )* }
{ $( $prepared_value:tt )* }
{ $counter:expr }
$(#[$m:meta])*
$variant:ident
$($more_variants:tt)*
) => {
expect_enum!(@__
$(#[$tm])*
$type_name
$values_name
$bitwidth_name
{ $( $prepared_variant )* $(#[$m])* $variant = $counter, }
{ $( $prepared_value )* $type_name::$variant , }
{ $counter + 1 }
$( $more_variants )*
);
};
($(#[$tm:meta])*
enum $type_name:ident [$values_name:ident; $bitwidth_name:ident]
{ $( $(#[$m:meta])* $variant_name:ident ),* $(,)? }
) => {
expect_enum!(@__ $(#[$tm])* $type_name $values_name $bitwidth_name {} {} { 0 } $( $(#[$m])* $variant_name )* );
};
}
expect_enum! {
#[derive(Debug)]
enum Expect [EXPECT_VALUES; EXPECT_BITSIZE] {
ListValue,
ListComma,
TupleValue,
TupleComma,
DataMapKey,
DataMapColon,
DataMapValue,
DataMapComma,
KwMapKey,
KwMapColon,
KwMapValue,
KwMapComma,
}
}
struct ExpectStack {
stack: bitstack::BitStack<EXPECT_BITSIZE, 2>,
}
impl ExpectStack {
fn last(&self) -> Option<Expect> {
self.stack.last().map(|n| EXPECT_VALUES[n])
}
fn replace_last(&mut self, replacement: Expect) {
self.stack.replace_last(replacement as usize);
}
fn push(&mut self, value: Expect) {
self.stack.push(value as usize);
}
fn pop(&mut self) -> Option<Expect> {
self.stack.pop().map(|n| EXPECT_VALUES[n])
}
}
impl Default for ExpectStack {
fn default() -> Self {
Self {
stack: bitstack::BitStack::new(),
}
}
}
mod bitstack {
use std::ops::Shl;
use smallvec::SmallVec;
pub struct BitStack<const B: usize, const N: usize = 1> {
store: SmallVec<[u64; N]>,
len: usize,
}
struct ValueAddr {
bucket: usize,
bitpos: usize,
}
impl<const B: usize, const N: usize> BitStack<B, N> {
pub const fn new() -> Self {
debug_assert!(N > 0, "N must be greater zero");
debug_assert!(
B > 0 && B < 64,
"B must be greater zero and smaller than 64"
);
debug_assert!(64 % B == 0, "B must be a factor of 64");
Self {
store: SmallVec::new_const(),
len: 0,
}
}
const VALUE_MASK: u64 = const { (1 << B) - 1 };
const BUCKET_SHIFT_DIV_B: u32 = const { (64 / B).trailing_zeros() };
const BITPOS_MASK: usize = const { (64 / B) - 1 };
const BITPOS_SHIFT_MUL_B: u32 = B.ilog2();
pub fn replace_last(&mut self, replacement: usize) {
let a = self.value_addr(self.len - 1);
self.write_value(a, replacement)
}
pub fn push(&mut self, value: usize) {
let a = self.value_addr(self.len);
if a.bucket >= self.store.len() {
self.store.push(0);
}
self.len += 1;
self.write_value(a, value)
}
pub fn last(&self) -> Option<usize> {
if self.len > 0 {
Some(self.read_value(self.value_addr(self.len - 1)))
} else {
None
}
}
pub fn pop(&mut self) -> Option<usize> {
if self.len > 0 {
self.len -= 1;
Some(self.read_value(self.value_addr(self.len)))
} else {
None
}
}
fn value_addr(&self, value_idx: usize) -> ValueAddr {
ValueAddr {
bucket: value_idx >> Self::BUCKET_SHIFT_DIV_B,
bitpos: (value_idx & Self::BITPOS_MASK) << Self::BITPOS_SHIFT_MUL_B,
}
}
fn read_value(&self, a: ValueAddr) -> usize {
((self.store[a.bucket] >> a.bitpos) & Self::VALUE_MASK) as usize
}
fn write_value(&mut self, a: ValueAddr, v: usize) {
self.store[a.bucket] = self.store[a.bucket] & !Self::VALUE_MASK.shl(a.bitpos)
| (v as u64 & Self::VALUE_MASK) << a.bitpos;
}
}
#[cfg(test)]
mod tests {
use super::*;
impl<const B: usize, const N: usize> BitStack<B, N> {
fn iter(&self) -> impl Iterator<Item = usize> {
Iter(0, self)
}
}
struct Iter<'a, const B: usize, const N: usize>(usize, &'a BitStack<B, N>);
impl<'a, const B: usize, const N: usize> Iterator for Iter<'a, B, N> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.0 < self.1.len {
let elem = self.1.read_value(self.1.value_addr(self.0));
self.0 += 1;
Some(elem)
} else {
None
}
}
}
#[test]
fn test_suspicous() {
let mut stack: BitStack<4, 1> = BitStack::new();
for i in 0..8 {
stack.push(i);
}
stack.pop();
stack.push(4);
assert_eq!(
vec![0, 1, 2, 3, 4, 5, 6, 4],
stack.iter().collect::<Vec<_>>()
);
}
}
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use serde::{de::IgnoredAny, Deserialize};
fn from_str<'a, T: Deserialize<'a>>(input: &'a str) -> Result<T, String> {
super::from_str(input).map_err(|e| format!("{e}"))
}
#[test]
fn test_bool() {
assert_eq!(Ok(true), from_str("true"));
assert_eq!(Ok(false), from_str("false"));
}
#[test]
fn test_i8() {
assert_eq!(Ok(0_i8), from_str("0"));
assert_eq!(Ok(-3_i8), from_str("-3"));
assert_eq!(Ok(-128_i8), from_str("-128"));
assert_eq!(Ok(127_i8), from_str("127"));
}
#[test]
fn test_u8() {
assert_eq!(Ok(0_u8), from_str("0"));
assert_eq!(Ok(3_u8), from_str("3"));
assert_eq!(Ok(128_u8), from_str("128"));
assert_eq!(Ok(255_u8), from_str("255"));
}
#[test]
fn test_f64() {
assert_eq!(Ok(123.0_f64), from_str("123"));
assert_eq!(Ok(1.0_f64), from_str("1"));
assert_eq!(Ok(1.2_f64), from_str("1.2"));
assert_eq!(Ok(0.01_f64), from_str("0.01"));
assert_eq!(Ok(-3.00001_f64), from_str("-3.00001"));
}
#[test]
fn test_strings() {
assert_eq!(Ok('c'), from_str(r#""c""#));
assert_eq!(Ok("abcd".to_string()), from_str(r#""abcd""#));
assert_eq!(Ok(""), from_str(r#""""#));
assert_eq!(Ok("abcd"), from_str(r#""abcd""#));
}
#[test]
fn test_bytes() {
assert_eq!(Ok(b"0123" as &[u8]), from_str(r#""0123""#));
assert_eq!(
Ok("abcd".into()),
from_str::<String>(r#"[97, 98, 99, 100]"#)
);
}
#[test]
fn test_unit() {
assert_eq!(Ok(()), from_str("null"))
}
#[test]
fn test_option() {
assert_eq!(Ok(None), from_str::<Option<String>>("null"));
assert_eq!(Ok(Some("foobar")), from_str::<Option<&str>>(r#""foobar""#));
assert_eq!(Ok(None), from_str::<Option<u32>>("null"));
assert_eq!(Ok(Some(42)), from_str::<Option<u32>>("42"));
}
#[test]
fn test_seq() {
assert_eq!(
Ok(vec![42, 11, 8765]),
from_str::<Vec<u32>>("[42, 11, 8765]")
);
}
#[test]
fn test_unit_struct() {
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Foo;
assert_eq!(Ok(Foo), from_str("Foo()"));
assert_eq!(Ok(Foo), from_str("Foo{}"));
}
#[test]
fn test_tuple() {
assert_eq!(Ok((1, 2, 3)), from_str("[1, 2, 3]"));
assert_eq!(Ok([1u8, 2, 3]), from_str("[1, 2, 3]"));
}
#[test]
fn test_newtype_struct() {
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Foo(u32);
assert_eq!(Ok(Foo(1)), from_str("Foo(1)"));
}
#[test]
fn test_newtype_struct_autocoerce() {
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Foo(u32);
assert_eq!(Ok(Foo(1)), from_str("1"));
}
#[test]
fn test_tuple_struct() {
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Rgb(u8, u8, u8);
assert_eq!(Ok(Rgb(127, 32, 87)), from_str("Rgb(127, 32, 87)"));
}
#[test]
fn test_unit_variant() {
#[derive(Deserialize, Debug, PartialEq, Eq)]
enum TrafficLight {
Red,
Orange,
Green,
}
assert_eq!(Ok(TrafficLight::Green), from_str(r#""Green""#));
assert_eq!(Ok(TrafficLight::Green), from_str(r#"Green()"#));
assert_eq!(Ok(TrafficLight::Green), from_str(r#"Green{}"#));
}
#[derive(Deserialize, Debug, PartialEq, Eq)]
enum E {
A(u8),
B(u32, bool),
C(),
D,
Z { x: i8, y: i8 },
}
#[test]
fn test_newtype_variant_a() {
assert_eq!(Ok(E::A(255)), from_str(r#"A(255)"#));
}
#[test]
fn test_newtype_variant_d() {
assert_eq!(Ok(E::D), from_str(r#""D""#));
assert_eq!(Ok(E::D), from_str(r#"D()"#));
assert_eq!(Ok(E::D), from_str(r#"D{}"#));
}
#[test]
fn test_newtype_variant_c() {
assert_eq!(Ok(E::C()), from_str(r#""C""#));
assert_eq!(Ok(E::C()), from_str(r#"C()"#));
assert_eq!(Ok(E::C()), from_str(r#"C{}"#));
}
#[test]
fn test_newtype_variant_b() {
assert_eq!(Ok(E::B(42, true)), from_str(r#"B(42, true)"#));
}
#[test]
fn test_newtype_variant_z_as_struct() {
assert_eq!(Ok(E::Z { x: 1, y: -9 }), from_str(r#"Z { x: 1, y: -9 }"#));
}
#[test]
fn test_newtype_variant_z_as_tuple() {
assert_eq!(Ok(E::Z { x: 33, y: -87 }), from_str(r#"Z(33, -87)"#));
}
#[test]
fn test_map() {
let exp = {
let mut m = HashMap::new();
m.insert("foo", 12);
m.insert("bar", 9001);
m
};
assert_eq!(Ok(&exp), from_str(r#"{"foo": 12, "bar": 9001}"#).as_ref());
assert_eq!(Ok(&exp), from_str(r#"{foo: 12, bar: 9001}"#).as_ref());
}
#[test]
fn test_struct() {
#[derive(Deserialize, PartialEq, Eq, Debug)]
#[serde(rename = "quux")]
struct Foo {
age: usize,
hobby: String,
}
assert_eq!(
Ok(Foo {
age: 21,
hobby: "programming".to_string(),
}),
from_str(r#"quux { age: 21, hobby: "programming", }"#)
);
assert_eq!(
Ok(Foo {
age: 21,
hobby: "programming".to_string(),
}),
from_str(r#"quux { age: 21, hobby: "programming" }"#)
);
assert_eq!(
Ok(Foo {
age: 21,
hobby: "programming".to_string(),
}),
from_str(r#"quux { hobby: "programming", age: 21 }"#)
);
assert_eq!(
Ok(Foo {
age: 21,
hobby: "programming".to_string(),
}),
from_str(r#"{ hobby: "programming", age: 21 }"#)
);
}
#[test]
fn test_nested_struct() {
#[derive(Deserialize, PartialEq, Eq, Debug)]
struct Foo {
age: usize,
bar: Bar,
}
#[derive(Deserialize, PartialEq, Eq, Debug)]
struct Bar {
name: String,
}
assert_eq!(
Ok(Foo {
age: 18,
bar: Bar {
name: "katie".to_string()
}
}),
from_str(r#"{age: 18, bar: Bar { name: "katie" }}"#)
);
}
#[test]
fn test_skip() {
#[derive(Deserialize, PartialEq, Eq, Debug)]
struct Foo {
age: usize,
#[serde(skip)]
hobby: String,
}
assert_eq!(
Ok(Foo {
age: 21,
hobby: String::new(),
}),
from_str(r#"Foo { age: 21, hobby: "nothing", x: 99.3, }"#)
);
}
#[derive(Deserialize, PartialEq, Eq, Debug)]
#[allow(dead_code)]
struct Hobby(String);
#[derive(Deserialize, PartialEq, Eq, Debug)]
#[allow(dead_code)]
struct Person {
name: String,
age: u32,
hobby: Hobby,
#[serde(default)]
friends: Vec<Person>,
}
#[test]
fn test_defaults() {
let s = r#"Person("pete", 10, "reading")"#;
assert_eq!(
Ok(Person {
name: "pete".to_string(),
age: 10,
hobby: Hobby("reading".to_string()),
friends: vec![]
}),
from_str(s)
);
}
#[test]
fn test_escaped_strings() {
let s = r#"
[
"\"cogito, ergo sum\" – René Descartes",
"\"It is not the man who has too little,\nbut the man who craves more, that is poor.\" – Seneca",
"\"Our problem is not that we aim too high and miss, \
but that we aim too low and hit.\" – Aristotele"
]"#;
assert_eq!(
Ok(vec![
r#""cogito, ergo sum" – René Descartes"#.to_string(),
r#""It is not the man who has too little,
but the man who craves more, that is poor." – Seneca"#.to_string(),
r#""Our problem is not that we aim too high and miss, but that we aim too low and hit." – Aristotele"#.to_string(),
]),
from_str(s),
);
}
#[test]
fn test_readme_example() {
let s = r#"
Person {
name: "pete",
age: 10,
hobby: "reading",
friends: [
{ name: "tom", age: 33, hobby: "writing" },
Person("mike", 9, Hobby("transpiling"), []),
Person { name: "josh", hobby: "dreaming", age: 12 },
]
}
"#;
assert_eq!(
Ok(Person {
name: "pete".to_string(),
age: 10,
hobby: Hobby("reading".to_string(),),
friends: vec![
Person {
name: "tom".to_string(),
age: 33,
hobby: Hobby("writing".to_string(),),
friends: vec![],
},
Person {
name: "mike".to_string(),
age: 9,
hobby: Hobby("transpiling".to_string(),),
friends: vec![],
},
Person {
name: "josh".to_string(),
age: 12,
hobby: Hobby("dreaming".to_string()),
friends: vec![],
}
],
}),
from_str::<Person>(s)
);
}
#[test]
fn test_ignored_any() {
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Foo {
a: usize,
b: String,
}
assert_eq!(
Ok(Foo {
a: 12,
b: "foo".to_string()
}),
from_str::<Foo>(
r#"
Foo {
x: [1, [2, {"a": "b"}, 3], 4],
a: 12,
y: Quux { hallo: true, hello: 23 },
b: "foo",
z: {"abc": 23.4, "def": 45.6}
}"#
)
);
}
#[test]
fn test_ignored_field_in_the_middle() {
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Foo {
a: usize,
b: String,
}
assert_eq!(
Ok(Foo {
a: 12,
b: "foo".to_string()
}),
from_str::<Foo>(r#"Foo { x: { i: 10, j: 20, k: 30 }, a: 12, b: "foo" }"#)
);
}
#[test]
fn test_ignore_list() {
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"[]"#));
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"[1]"#));
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"[1, 2]"#));
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"[1, 2,]"#));
assert!(from_str::<IgnoredAny>(r#"[1,2,,]"#).is_err());
assert!(from_str::<IgnoredAny>(r#"[,]"#).is_err());
}
#[test]
fn test_ignore_list_nested() {
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"[[]]"#));
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"[[], []]"#));
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"[[1, 2]]"#));
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"[[1, 2],]"#));
assert_eq!(
Ok(IgnoredAny),
from_str::<IgnoredAny>(r#"[[[[[[1,]]],], 2],]"#)
);
assert!(from_str::<IgnoredAny>(r#"[[[[[[1,,]]],], 2],]"#).is_err());
assert!(from_str::<IgnoredAny>(r#"[[,]]"#).is_err());
}
#[test]
fn test_ignore_map() {
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"{}"#));
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"{1: "a"}"#));
assert_eq!(
Ok(IgnoredAny),
from_str::<IgnoredAny>(r#"{1: "a", 2: "b"}"#)
);
assert_eq!(
Ok(IgnoredAny),
from_str::<IgnoredAny>(r#"{1: true, 2: false,}"#)
);
assert!(from_str::<IgnoredAny>(r#"{1: 2,,}"#).is_err());
assert!(from_str::<IgnoredAny>(r#"{,}"#).is_err());
assert!(from_str::<IgnoredAny>(r#"Foo {1: "a"}"#).is_err());
assert_eq!(Ok(IgnoredAny), from_str::<IgnoredAny>(r#"Foo {abc: "a"}"#));
assert_eq!(
Ok(IgnoredAny),
from_str::<IgnoredAny>(r#"Foo {abc: "a", def: null}"#)
);
assert_eq!(
Ok(IgnoredAny),
from_str::<IgnoredAny>(r#"Foo("a", 1, true)"#)
);
}
}