use alloc::string::{String, ToString};
use core::fmt;
use serde::de::value::Error as DeError;
use serde::de::{
DeserializeOwned, Deserializer, Error as _, IntoDeserializer, MapAccess, SeqAccess, Visitor,
};
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
use crate::value::{Classified, Number, Value};
impl Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Value::Null => serializer.serialize_unit(),
Value::Bool(value) => serializer.serialize_bool(*value),
Value::Number(number) => match number.classify() {
Some(Classified::I64(value)) => serializer.serialize_i64(value),
Some(Classified::U64(value)) => serializer.serialize_u64(value),
Some(Classified::F64(value)) => serializer.serialize_f64(value),
None => Err(<S::Error as serde::ser::Error>::custom(non_finite(number))),
},
Value::String(text) => serializer.serialize_str(text),
Value::Array(items) => {
let mut seq = serializer.serialize_seq(Some(items.len()))?;
for item in items {
seq.serialize_element(item)?;
}
seq.end()
}
Value::Object(members) => {
let mut map = serializer.serialize_map(Some(members.len()))?;
for (key, value) in members {
map.serialize_entry(key, value)?;
}
map.end()
}
}
}
}
impl<'de> serde::Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(ValueVisitor)
}
}
struct ValueVisitor;
impl<'de> Visitor<'de> for ValueVisitor {
type Value = Value;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("any JSON value")
}
fn visit_bool<E>(self, value: bool) -> Result<Value, E> {
Ok(Value::Bool(value))
}
fn visit_i64<E>(self, value: i64) -> Result<Value, E> {
Ok(number(value.to_string()))
}
fn visit_u64<E>(self, value: u64) -> Result<Value, E> {
Ok(number(value.to_string()))
}
fn visit_i128<E>(self, value: i128) -> Result<Value, E> {
Ok(number(value.to_string()))
}
fn visit_u128<E>(self, value: u128) -> Result<Value, E> {
Ok(number(value.to_string()))
}
fn visit_f64<E>(self, value: f64) -> Result<Value, E> {
Ok(Value::from(value))
}
fn visit_str<E>(self, value: &str) -> Result<Value, E> {
Ok(Value::String(String::from(value)))
}
fn visit_string<E>(self, value: String) -> Result<Value, E> {
Ok(Value::String(value))
}
fn visit_unit<E>(self) -> Result<Value, E> {
Ok(Value::Null)
}
fn visit_none<E>(self) -> Result<Value, E> {
Ok(Value::Null)
}
fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut items = alloc::vec::Vec::new();
while let Some(item) = seq.next_element()? {
items.push(item);
}
Ok(Value::Array(items))
}
fn visit_map<A>(self, mut map: A) -> Result<Value, A::Error>
where
A: MapAccess<'de>,
{
let mut members = alloc::vec::Vec::new();
while let Some((key, value)) = map.next_entry::<String, Value>()? {
members.push((key, value));
}
Ok(Value::Object(members))
}
}
fn number(text: String) -> Value {
Value::Number(Number::from_normalized(text))
}
pub fn from_value<T: DeserializeOwned>(value: Value) -> Result<T, serde::de::value::Error> {
T::deserialize(value)
}
macro_rules! parse_int_method {
($method:ident, $visit:ident, $ty:ty) => {
fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::Number(text) => {
let raw = text.as_str();
match raw.parse::<$ty>() {
Ok(value) => visitor.$visit(value),
Err(_) => Err(DeError::custom(alloc::format!(
"number `{raw}` does not fit `{}`",
core::stringify!($ty)
))),
}
}
other => Err(type_error(core::stringify!($ty), other)),
}
}
};
}
macro_rules! parse_float_method {
($method:ident, $visit:ident, $ty:ty) => {
fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::Number(text) => {
let raw = text.as_str();
match raw.parse::<$ty>() {
Ok(value) if value.is_finite() => visitor.$visit(value),
Ok(_) => Err(DeError::custom(non_finite(&text))),
Err(_) => Err(DeError::custom(alloc::format!(
"number `{raw}` does not fit `{}`",
core::stringify!($ty)
))),
}
}
other => Err(type_error(core::stringify!($ty), other)),
}
}
};
}
impl<'de> Deserializer<'de> for Value {
type Error = DeError;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::Null => visitor.visit_unit(),
Value::Bool(value) => visitor.visit_bool(value),
Value::Number(text) => visit_number(text, visitor),
Value::String(text) => visitor.visit_string(text),
Value::Array(items) => visitor.visit_seq(SeqDeserializer(items.into_iter())),
Value::Object(members) => visitor.visit_map(MapDeserializer::new(members)),
}
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::Bool(value) => visitor.visit_bool(value),
other => Err(type_error("a boolean", other)),
}
}
parse_int_method!(deserialize_i8, visit_i8, i8);
parse_int_method!(deserialize_i16, visit_i16, i16);
parse_int_method!(deserialize_i32, visit_i32, i32);
parse_int_method!(deserialize_i64, visit_i64, i64);
parse_int_method!(deserialize_u8, visit_u8, u8);
parse_int_method!(deserialize_u16, visit_u16, u16);
parse_int_method!(deserialize_u32, visit_u32, u32);
parse_int_method!(deserialize_u64, visit_u64, u64);
parse_int_method!(deserialize_i128, visit_i128, i128);
parse_int_method!(deserialize_u128, visit_u128, u128);
parse_float_method!(deserialize_f32, visit_f32, f32);
parse_float_method!(deserialize_f64, visit_f64, f64);
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::String(text) => {
let mut chars = text.chars();
match (chars.next(), chars.next()) {
(Some(c), None) => visitor.visit_char(c),
_ => Err(DeError::custom(alloc::format!(
"expected one character, found the string `{text}`"
))),
}
}
other => Err(type_error("a character", other)),
}
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::String(text) => visitor.visit_str(&text),
other => Err(type_error("a string", other)),
}
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::String(text) => visitor.visit_string(text),
other => Err(type_error("a string", other)),
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::Null => visitor.visit_none(),
value => visitor.visit_some(value),
}
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::Object(members) => visitor.visit_map(MapDeserializer::new(members)),
other => Err(type_error("a map", other)),
}
}
fn deserialize_struct<V>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_map(visitor)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::Array(items) => visitor.visit_seq(SeqDeserializer(items.into_iter())),
other => Err(type_error("a sequence", other)),
}
}
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_seq(visitor)
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::Null => visitor.visit_unit(),
other => Err(type_error("`()`", other)),
}
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_unit(visitor)
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
Value::String(variant) => visitor.visit_enum(variant.into_deserializer()),
Value::Object(members) => visitor.visit_enum(EnumDeserializer(members.into_iter())),
other => Err(type_error("an enum", other)),
}
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_string(visitor)
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_any(visitor)
}
serde::forward_to_deserialize_any! { bytes byte_buf }
}
impl Value {
fn kind_name(&self) -> &'static str {
match self {
Value::Null => "`null`",
Value::Bool(_) => "a boolean",
Value::Number(_) => "a number",
Value::String(_) => "a string",
Value::Array(_) => "an array",
Value::Object(_) => "an object",
}
}
}
fn type_error(expected: &str, found: Value) -> DeError {
DeError::custom(alloc::format!(
"expected {expected}, found {}",
found.kind_name()
))
}
fn visit_number<'de, V>(number: Number, visitor: V) -> Result<V::Value, DeError>
where
V: Visitor<'de>,
{
match number.classify() {
Some(Classified::I64(value)) => visitor.visit_i64(value),
Some(Classified::U64(value)) => visitor.visit_u64(value),
Some(Classified::F64(value)) => visitor.visit_f64(value),
None => Err(DeError::custom(non_finite(&number))),
}
}
fn non_finite(number: &Number) -> alloc::string::String {
alloc::format!("number `{number}` is not a finite float and cannot be represented")
}
struct SeqDeserializer(alloc::vec::IntoIter<Value>);
impl<'de> SeqAccess<'de> for SeqDeserializer {
type Error = DeError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
self.0
.next()
.map(|value| seed.deserialize(value))
.transpose()
}
fn size_hint(&self) -> Option<usize> {
Some(self.0.len())
}
}
struct MapDeserializer {
iter: alloc::vec::IntoIter<(String, Value)>,
value: Option<Value>,
}
impl MapDeserializer {
fn new(members: alloc::vec::Vec<(String, Value)>) -> Self {
Self {
iter: members.into_iter(),
value: None,
}
}
}
impl<'de> MapAccess<'de> for MapDeserializer {
type Error = DeError;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: serde::de::DeserializeSeed<'de>,
{
self.iter
.next()
.map(|(key, value)| {
self.value = Some(value);
seed.deserialize(key.into_deserializer())
})
.transpose()
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
match self.value.take() {
Some(value) => seed.deserialize(value),
None => Err(DeError::custom("value is missing")),
}
}
fn size_hint(&self) -> Option<usize> {
Some(self.iter.len())
}
}
struct EnumDeserializer(alloc::vec::IntoIter<(String, Value)>);
impl<'de> serde::de::EnumAccess<'de> for EnumDeserializer {
type Error = DeError;
type Variant = EnumVariantDeserializer;
fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
match self.0.next() {
Some((variant, value)) => {
let variant = seed.deserialize(variant.into_deserializer())?;
Ok((variant, EnumVariantDeserializer(value)))
}
None => Err(DeError::custom("enum must have exactly one member")),
}
}
}
struct EnumVariantDeserializer(Value);
impl<'de> serde::de::VariantAccess<'de> for EnumVariantDeserializer {
type Error = DeError;
fn unit_variant(self) -> Result<(), Self::Error> {
match self.0 {
Value::Null => Ok(()),
other => Err(type_error("`null` content for a unit variant", other)),
}
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
seed.deserialize(self.0)
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.0 {
Value::Array(items) => visitor.visit_seq(SeqDeserializer(items.into_iter())),
other => Err(type_error("a tuple variant content", other)),
}
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.0 {
Value::Object(members) => visitor.visit_map(MapDeserializer::new(members)),
other => Err(type_error("a struct variant content", other)),
}
}
}
#[cfg(test)]
mod from_value_tests {
use super::*;
use alloc::vec;
use alloc::vec::Vec;
#[derive(Debug, PartialEq, serde::Deserialize)]
struct Reply {
answer: String,
score: f32,
}
#[test]
fn from_value_reads_a_struct_from_repaired_input() {
let value = crate::parse("{answer: 'yes', score: 0.9,}").expect("repairs");
let reply: Reply = from_value(value).expect("deserializes");
assert_eq!(
reply,
Reply {
answer: String::from("yes"),
score: 0.9
}
);
}
#[test]
fn from_value_keeps_64_bit_integer_text_exact() {
#[derive(Debug, PartialEq, serde::Deserialize)]
struct Ids {
big: u64,
small: i64,
}
let value = crate::parse("{big: 1234567890123456789, small: -9223372036854775808}")
.expect("repairs");
let ids: Ids = from_value(value).expect("deserializes");
assert_eq!(
ids,
Ids {
big: 1234567890123456789,
small: i64::MIN
}
);
}
#[test]
fn from_value_treats_null_as_none() {
#[derive(Debug, PartialEq, serde::Deserialize)]
struct Maybe {
a: Option<i32>,
b: Option<i32>,
}
let value = crate::parse(r#"{"a": null, "b": 2}"#).expect("parses");
let got: Maybe = from_value(value).expect("deserializes");
assert_eq!(
got,
Maybe {
a: None,
b: Some(2)
}
);
}
#[test]
fn from_value_walks_sequences() {
let value = crate::parse("[1, 2, 3]").expect("parses");
let items: Vec<i64> = from_value(value).expect("deserializes");
assert_eq!(items, vec![1, 2, 3]);
}
#[test]
fn from_value_supports_externally_tagged_enums() {
#[derive(Debug, PartialEq, serde::Deserialize)]
enum Step {
Done,
Note(String),
}
let value = crate::parse(r#"{"Note": "x"}"#).expect("parses");
let step: Step = from_value(value).expect("deserializes");
assert_eq!(step, Step::Note(String::from("x")));
let value = crate::parse(r#""Done""#).expect("parses");
let step: Step = from_value(value).expect("deserializes");
assert_eq!(step, Step::Done);
}
#[test]
fn from_value_errors_on_non_finite_numbers() {
let value = crate::parse("1e400").expect("repairs");
let error = from_value::<f64>(value).expect_err("non-finite");
assert!(alloc::format!("{error}").contains("finite"));
}
#[test]
fn from_value_rejects_f32_overflow_to_infinity() {
let value = crate::parse("1e40").expect("repairs");
let error = from_value::<f32>(value).expect_err("overflows f32 to inf");
assert!(alloc::format!("{error}").contains("finite"));
let value = crate::parse("3.5").expect("repairs");
assert_eq!(from_value::<f32>(value).expect("in range"), 3.5_f32);
let value = crate::parse("1e40").expect("repairs");
assert!(from_value::<f64>(value).is_ok());
}
#[test]
fn from_value_errors_instead_of_overflowing_integer_targets() {
let value = crate::parse("12345678901234567890").expect("repairs");
assert!(from_value::<i64>(value).is_err());
let value = crate::parse("-1").expect("parses");
assert!(from_value::<u64>(value).is_err());
}
#[test]
fn deserializing_floats_into_a_value_always_renders_valid_json() {
use serde::de::IntoDeserializer;
use serde::de::value::F64Deserializer;
for (float, want) in [
(f64::NAN, "null"),
(f64::INFINITY, "null"),
(f64::NEG_INFINITY, "null"),
(1.0, "1.0"),
(1e300, "1e300"),
(-2.5e-7, "-2.5e-7"),
] {
let source: F64Deserializer<DeError> = float.into_deserializer();
let value = <Value as serde::Deserialize>::deserialize(source).expect("any float");
let text = value.to_json_string();
assert_eq!(text, want, "float {float:?}");
assert!(crate::validate(&text).is_ok(), "{text} must be valid JSON");
}
let value = crate::parse("[1.0, 2.5]").expect("parses");
let again: Value = from_value(value.clone()).expect("value to value");
assert_eq!(again, value);
}
#[test]
fn from_value_reads_128_bit_integers_exactly() {
#[derive(Debug, PartialEq, serde::Deserialize)]
struct Ids {
big: u128,
small: i128,
}
let value = crate::parse(
"{big: 340282366920938463463374607431768211455, \
small: -170141183460469231731687303715884105728}",
)
.expect("repairs");
let ids: Ids = from_value(value).expect("deserializes");
assert_eq!(
ids,
Ids {
big: u128::MAX,
small: i128::MIN
}
);
let value = crate::parse("340282366920938463463374607431768211456").expect("repairs");
assert!(from_value::<u128>(value).is_err());
let value = crate::parse("1.5").expect("repairs");
assert!(from_value::<i128>(value).is_err());
}
}