Apply enum PR

https://github.com/nox/serde_urlencoded/pull/30
This commit is contained in:
Douman 2018-07-12 18:34:27 +03:00
parent 34e0a38ee9
commit 1b5bef811b
3 changed files with 103 additions and 2 deletions

View File

@ -1,6 +1,7 @@
//! Deserialization support for the `application/x-www-form-urlencoded` format. //! Deserialization support for the `application/x-www-form-urlencoded` format.
use serde::de::{self, IntoDeserializer}; use serde::de::{self, DeserializeSeed, EnumAccess, IntoDeserializer, VariantAccess, Visitor};
use serde::de::Error as de_Error;
use serde::de::value::MapDeserializer; use serde::de::value::MapDeserializer;
use std::borrow::Cow; use std::borrow::Cow;
@ -197,6 +198,12 @@ impl<'de> de::Deserializer<'de> for Part<'de> {
visitor.visit_some(self) visitor.visit_some(self)
} }
fn deserialize_enum<V>(self, _name: &'static str, _variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor<'de>,
{
visitor.visit_enum(ValueEnumAccess { value: self.0 })
}
forward_to_deserialize_any! { forward_to_deserialize_any! {
char char
str str
@ -210,7 +217,6 @@ impl<'de> de::Deserializer<'de> for Part<'de> {
struct struct
identifier identifier
tuple tuple
enum
ignored_any ignored_any
seq seq
map map
@ -230,3 +236,62 @@ impl<'de> de::Deserializer<'de> for Part<'de> {
f64 => deserialize_f64, f64 => deserialize_f64,
} }
} }
/// Provides access to a keyword which can be deserialized into an enum variant. The enum variant
/// must be a unit variant, otherwise deserialization will fail.
struct ValueEnumAccess<'de> {
value: Cow<'de, str>,
}
impl<'de> EnumAccess<'de> for ValueEnumAccess<'de> {
type Error = Error;
type Variant = UnitOnlyVariantAccess;
fn variant_seed<V>(
self,
seed: V,
) -> Result<(V::Value, Self::Variant), Self::Error>
where V: DeserializeSeed<'de>,
{
let variant = seed.deserialize(self.value.into_deserializer())?;
Ok((variant, UnitOnlyVariantAccess))
}
}
/// A visitor for deserializing the contents of the enum variant. As we only support
/// `unit_variant`, all other variant types will return an error.
struct UnitOnlyVariantAccess;
impl<'de> VariantAccess<'de> for UnitOnlyVariantAccess {
type Error = Error;
fn unit_variant(self) -> Result<(), Self::Error> {
Ok(())
}
fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
where T: DeserializeSeed<'de>,
{
Err(Error::custom("expected unit variant"))
}
fn tuple_variant<V>(
self,
_len: usize,
_visitor: V,
) -> Result<V::Value, Self::Error>
where V: Visitor<'de>,
{
Err(Error::custom("expected unit variant"))
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Self::Error>
where V: Visitor<'de>,
{
Err(Error::custom("expected unit variant"))
}
}

View File

@ -1,4 +1,6 @@
extern crate serde_urlencoded; extern crate serde_urlencoded;
#[macro_use]
extern crate serde_derive;
#[test] #[test]
fn deserialize_bytes() { fn deserialize_bytes() {
@ -40,3 +42,21 @@ fn deserialize_unit() {
assert_eq!(serde_urlencoded::from_str("&&"), Ok(())); assert_eq!(serde_urlencoded::from_str("&&"), Ok(()));
assert!(serde_urlencoded::from_str::<()>("first=23").is_err()); assert!(serde_urlencoded::from_str::<()>("first=23").is_err());
} }
#[derive(Deserialize, Debug, PartialEq, Eq)]
enum X {
A,
B,
C,
}
#[test]
fn deserialize_unit_enum() {
let result = vec![
("one".to_owned(), X::A),
("two".to_owned(), X::B),
("three".to_owned(), X::C)
];
assert_eq!(serde_urlencoded::from_str("one=A&two=B&three=C"), Ok(result));
}

View File

@ -1,4 +1,6 @@
extern crate serde_urlencoded; extern crate serde_urlencoded;
#[macro_use]
extern crate serde_derive;
#[test] #[test]
fn serialize_option_map_int() { fn serialize_option_map_int() {
@ -32,3 +34,17 @@ fn serialize_map_bool() {
assert_eq!(serde_urlencoded::to_string(params), assert_eq!(serde_urlencoded::to_string(params),
Ok("one=true&two=false".to_owned())); Ok("one=true&two=false".to_owned()));
} }
#[derive(Serialize)]
enum X {
A,
B,
C,
}
#[test]
fn serialize_unit_enum() {
let params = &[("one", X::A), ("two", X::B), ("three", X::C)];
assert_eq!(serde_urlencoded::to_string(params),
Ok("one=A&two=B&three=C".to_owned()));
}