Skip to content

Commit

Permalink
Merge pull request #1135 from swlynch99/map-deserializer
Browse files Browse the repository at this point in the history
Implement `Deserializer` for `Map<String, Value>` and `&Map<String, Value>`
  • Loading branch information
dtolnay authored Oct 18, 2024
2 parents 2825e15 + c2540b0 commit b4954a9
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 104 deletions.
16 changes: 16 additions & 0 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,22 @@ macro_rules! delegate_iterator {
}
}

impl<'de> de::IntoDeserializer<'de, crate::Error> for Map<String, Value> {
type Deserializer = Self;

fn into_deserializer(self) -> Self::Deserializer {
self
}
}

impl<'de> de::IntoDeserializer<'de, crate::Error> for &'de Map<String, Value> {
type Deserializer = Self;

fn into_deserializer(self) -> Self::Deserializer {
self
}
}

//////////////////////////////////////////////////////////////////////////////

/// A view into a single entry in a map, which may either be vacant or occupied.
Expand Down
273 changes: 169 additions & 104 deletions src/value/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,21 +203,72 @@ where
}
}

fn visit_object<'de, V>(object: Map<String, Value>, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let len = object.len();
let mut deserializer = MapDeserializer::new(object);
let map = tri!(visitor.visit_map(&mut deserializer));
let remaining = deserializer.iter.len();
if remaining == 0 {
Ok(map)
} else {
Err(serde::de::Error::invalid_length(
len,
&"fewer elements in map",
))
impl<'de> serde::Deserializer<'de> for Map<String, Value> {
type Error = Error;

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let len = self.len();
let mut deserializer = MapDeserializer::new(self);
let map = tri!(visitor.visit_map(&mut deserializer));
let remaining = deserializer.iter.len();
if remaining == 0 {
Ok(map)
} else {
Err(serde::de::Error::invalid_length(
len,
&"fewer elements in map",
))
}
}

fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let mut iter = self.into_iter();
let (variant, value) = match iter.next() {
Some(v) => v,
None => {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}

visitor.visit_enum(EnumDeserializer {
variant,
value: Some(value),
})
}

fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
drop(self);
visitor.visit_unit()
}

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 identifier
}
}

Expand All @@ -238,7 +289,7 @@ impl<'de> serde::Deserializer<'de> for Value {
#[cfg(not(any(feature = "std", feature = "alloc")))]
Value::String(_) => unreachable!(),
Value::Array(v) => visit_array(v, visitor),
Value::Object(v) => visit_object(v, visitor),
Value::Object(v) => v.deserialize_any(visitor),
}
}

Expand Down Expand Up @@ -269,44 +320,24 @@ impl<'de> serde::Deserializer<'de> for Value {
#[inline]
fn deserialize_enum<V>(
self,
_name: &str,
_variants: &'static [&'static str],
name: &'static str,
variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let (variant, value) = match self {
Value::Object(value) => {
let mut iter = value.into_iter();
let (variant, value) = match iter.next() {
Some(v) => v,
None => {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
(variant, Some(value))
}
Value::String(variant) => (variant, None),
other => {
return Err(serde::de::Error::invalid_type(
other.unexpected(),
&"string or map",
));
}
};

visitor.visit_enum(EnumDeserializer { variant, value })
match self {
Value::Object(value) => value.deserialize_enum(name, variants, visitor),
Value::String(variant) => visitor.visit_enum(EnumDeserializer {
variant,
value: None,
}),
other => Err(serde::de::Error::invalid_type(
other.unexpected(),
&"string or map",
)),
}
}

#[inline]
Expand Down Expand Up @@ -436,7 +467,7 @@ impl<'de> serde::Deserializer<'de> for Value {
V: Visitor<'de>,
{
match self {
Value::Object(v) => visit_object(v, visitor),
Value::Object(v) => v.deserialize_any(visitor),
_ => Err(self.invalid_type(&visitor)),
}
}
Expand All @@ -452,7 +483,7 @@ impl<'de> serde::Deserializer<'de> for Value {
{
match self {
Value::Array(v) => visit_array(v, visitor),
Value::Object(v) => visit_object(v, visitor),
Value::Object(v) => v.deserialize_any(visitor),
_ => Err(self.invalid_type(&visitor)),
}
}
Expand Down Expand Up @@ -566,8 +597,10 @@ impl<'de> VariantAccess<'de> for VariantDeserializer {
where
V: Visitor<'de>,
{
use serde::de::Deserializer;

match self.value {
Some(Value::Object(v)) => visit_object(v, visitor),
Some(Value::Object(v)) => v.deserialize_any(visitor),
Some(other) => Err(serde::de::Error::invalid_type(
other.unexpected(),
&"struct variant",
Expand Down Expand Up @@ -708,21 +741,71 @@ where
}
}

fn visit_object_ref<'de, V>(object: &'de Map<String, Value>, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let len = object.len();
let mut deserializer = MapRefDeserializer::new(object);
let map = tri!(visitor.visit_map(&mut deserializer));
let remaining = deserializer.iter.len();
if remaining == 0 {
Ok(map)
} else {
Err(serde::de::Error::invalid_length(
len,
&"fewer elements in map",
))
impl<'de> serde::Deserializer<'de> for &'de Map<String, Value> {
type Error = Error;

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let len = self.len();
let mut deserializer = MapRefDeserializer::new(self);
let map = tri!(visitor.visit_map(&mut deserializer));
let remaining = deserializer.iter.len();
if remaining == 0 {
Ok(map)
} else {
Err(serde::de::Error::invalid_length(
len,
&"fewer elements in map",
))
}
}

fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let mut iter = self.into_iter();
let (variant, value) = match iter.next() {
Some(v) => v,
None => {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}

visitor.visit_enum(EnumRefDeserializer {
variant,
value: Some(value),
})
}

fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}

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 identifier
}
}

Expand All @@ -739,7 +822,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
Value::Number(n) => n.deserialize_any(visitor),
Value::String(v) => visitor.visit_borrowed_str(v),
Value::Array(v) => visit_array_ref(v, visitor),
Value::Object(v) => visit_object_ref(v, visitor),
Value::Object(v) => v.deserialize_any(visitor),
}
}

Expand Down Expand Up @@ -768,44 +851,24 @@ impl<'de> serde::Deserializer<'de> for &'de Value {

fn deserialize_enum<V>(
self,
_name: &str,
_variants: &'static [&'static str],
name: &'static str,
variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let (variant, value) = match self {
Value::Object(value) => {
let mut iter = value.into_iter();
let (variant, value) = match iter.next() {
Some(v) => v,
None => {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
(variant, Some(value))
}
Value::String(variant) => (variant, None),
other => {
return Err(serde::de::Error::invalid_type(
other.unexpected(),
&"string or map",
));
}
};

visitor.visit_enum(EnumRefDeserializer { variant, value })
match self {
Value::Object(value) => value.deserialize_enum(name, variants, visitor),
Value::String(variant) => visitor.visit_enum(EnumRefDeserializer {
variant,
value: None,
}),
other => Err(serde::de::Error::invalid_type(
other.unexpected(),
&"string or map",
)),
}
}

#[inline]
Expand Down Expand Up @@ -933,7 +996,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
V: Visitor<'de>,
{
match self {
Value::Object(v) => visit_object_ref(v, visitor),
Value::Object(v) => v.deserialize_any(visitor),
_ => Err(self.invalid_type(&visitor)),
}
}
Expand All @@ -949,7 +1012,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
{
match self {
Value::Array(v) => visit_array_ref(v, visitor),
Value::Object(v) => visit_object_ref(v, visitor),
Value::Object(v) => v.deserialize_any(visitor),
_ => Err(self.invalid_type(&visitor)),
}
}
Expand Down Expand Up @@ -1046,8 +1109,10 @@ impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> {
where
V: Visitor<'de>,
{
use serde::de::Deserializer;

match self.value {
Some(Value::Object(v)) => visit_object_ref(v, visitor),
Some(Value::Object(v)) => v.deserialize_any(visitor),
Some(other) => Err(serde::de::Error::invalid_type(
other.unexpected(),
&"struct variant",
Expand Down

0 comments on commit b4954a9

Please sign in to comment.