Skip to content

Commit 83b4ebd

Browse files
committed
de:variants:
* Implement VariantAccess for non unit enums * Add newtype_variant & struct_variant deserialization * Basic tests for both * Remove Unreachable impl for SerializationStructVariant
1 parent 56fead2 commit 83b4ebd

File tree

4 files changed

+93
-17
lines changed

4 files changed

+93
-17
lines changed

.vscode/launch.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"cargo": {
1212
"args": [
1313
"test",
14+
"--features=custom-error-messages",
1415
"--no-run",
1516
"--lib",
1617
"--package=serde-json-core"

src/de/enum_.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,56 @@ impl<'de, 'a> de::VariantAccess<'de> for UnitVariantAccess<'a, 'de> {
5353
Err(Error::InvalidType)
5454
}
5555
}
56+
57+
pub(crate) struct VariantAccess<'a, 'b> {
58+
de: &'a mut Deserializer<'b>,
59+
}
60+
61+
impl<'a, 'b> VariantAccess<'a, 'b> {
62+
pub(crate) fn new(de: &'a mut Deserializer<'b>) -> Self {
63+
VariantAccess { de }
64+
}
65+
}
66+
67+
impl<'a, 'de> de::EnumAccess<'de> for VariantAccess<'a, 'de> {
68+
type Error = Error;
69+
type Variant = Self;
70+
71+
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self)>
72+
where
73+
V: de::DeserializeSeed<'de>,
74+
{
75+
let variant = seed.deserialize(&mut *self.de)?;
76+
self.de.parse_object_colon()?;
77+
Ok((variant, self))
78+
}
79+
}
80+
81+
impl<'de, 'a> de::VariantAccess<'de> for VariantAccess<'a, 'de> {
82+
type Error = Error;
83+
84+
fn unit_variant(self) -> Result<()> {
85+
de::Deserialize::deserialize(self.de)
86+
}
87+
88+
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
89+
where
90+
T: de::DeserializeSeed<'de>,
91+
{
92+
seed.deserialize(self.de)
93+
}
94+
95+
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
96+
where
97+
V: de::Visitor<'de>,
98+
{
99+
de::Deserializer::deserialize_seq(self.de, visitor)
100+
}
101+
102+
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
103+
where
104+
V: de::Visitor<'de>,
105+
{
106+
de::Deserializer::deserialize_struct(self.de, "", fields, visitor)
107+
}
108+
}

src/de/mod.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use core::{fmt, str};
55

66
use serde::de::{self, Visitor};
77

8-
use self::enum_::UnitVariantAccess;
8+
use self::enum_::{UnitVariantAccess, VariantAccess};
99
use self::map::MapAccess;
1010
use self::seq::SeqAccess;
1111

@@ -585,6 +585,17 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
585585
{
586586
match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
587587
b'"' => visitor.visit_enum(UnitVariantAccess::new(self)),
588+
b'{' => {
589+
self.eat_char();
590+
let value = visitor.visit_enum(VariantAccess::new(self))?;
591+
match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
592+
b'}' => {
593+
self.eat_char();
594+
Ok(value)
595+
}
596+
_ => Err(Error::ExpectedSomeValue),
597+
}
598+
},
588599
_ => Err(Error::ExpectedSomeValue),
589600
}
590601
}
@@ -890,6 +901,11 @@ mod tests {
890901
assert!(crate::from_str::<Temperature>(r#"{ "temperature": -1 }"#).is_err());
891902
}
892903

904+
#[test]
905+
fn test_unit() {
906+
assert_eq!(crate::from_str::<()>(r#"null"#).unwrap(), ());
907+
}
908+
893909
#[test]
894910
fn newtype_struct() {
895911
#[derive(Deserialize, Debug, PartialEq)]
@@ -898,6 +914,28 @@ mod tests {
898914
assert_eq!(crate::from_str::<A>(r#"54"#).unwrap(), A(54));
899915
}
900916

917+
#[test]
918+
fn test_newtype_variant() {
919+
#[derive(Deserialize, Debug, PartialEq)]
920+
enum A {
921+
A(u32),
922+
}
923+
let a = A::A(54);
924+
let x = crate::from_str::<A>(r#"{"A":54}"#);
925+
assert_eq!(x, Ok(a));
926+
}
927+
928+
#[test]
929+
fn test_struct_variant() {
930+
#[derive(Deserialize, Debug, PartialEq)]
931+
enum A {
932+
A { x: u32, y: u16 },
933+
}
934+
let a = A::A { x: 54, y: 720 };
935+
let x = crate::from_str::<A>(r#"{"A": {"x":54,"y":720 } }"#);
936+
assert_eq!(x, Ok(a));
937+
}
938+
901939
#[test]
902940
#[cfg(not(feature = "custom-error-messages"))]
903941
fn struct_tuple() {

src/ser/mod.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -421,22 +421,6 @@ impl ser::SerializeMap for Unreachable {
421421
}
422422
}
423423

424-
impl ser::SerializeStructVariant for Unreachable {
425-
type Ok = ();
426-
type Error = Error;
427-
428-
fn serialize_field<T: ?Sized>(&mut self, _key: &'static str, _value: &T) -> Result<()>
429-
where
430-
T: ser::Serialize,
431-
{
432-
unreachable!()
433-
}
434-
435-
fn end(self) -> Result<Self::Ok> {
436-
unreachable!()
437-
}
438-
}
439-
440424
#[cfg(test)]
441425
mod tests {
442426
use serde_derive::Serialize;

0 commit comments

Comments
 (0)