Deserialization of Haskell style enums

This commit is contained in:
David Tolnay
2017-02-19 16:04:50 -08:00
parent 599a1b6607
commit 9a3c1243f4
4 changed files with 394 additions and 15 deletions
+45 -1
View File
@@ -21,7 +21,7 @@ use collections::{String, Vec};
use alloc::boxed::Box;
use de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqVisitor, MapVisitor,
EnumVisitor};
EnumVisitor, Unexpected};
/// Used from generated code to buffer the contents of the Deserializer when
/// deserializing untagged enums and internally tagged enums.
@@ -493,6 +493,50 @@ impl<T> Visitor for TaggedContentVisitor<T>
}
}
/// Used by generated code to deserialize an adjacently tagged enum.
///
/// Not public API.
pub enum TagOrContentField {
Tag,
Content,
}
/// Not public API.
pub struct TagOrContentFieldVisitor {
pub tag: &'static str,
pub content: &'static str,
}
impl DeserializeSeed for TagOrContentFieldVisitor {
type Value = TagOrContentField;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
deserializer.deserialize_str(self)
}
}
impl Visitor for TagOrContentFieldVisitor {
type Value = TagOrContentField;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{:?} or {:?}", self.tag, self.content)
}
fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
where E: de::Error
{
if field == self.tag {
Ok(TagOrContentField::Tag)
} else if field == self.content {
Ok(TagOrContentField::Content)
} else {
Err(de::Error::invalid_value(Unexpected::Str(field), &self))
}
}
}
/// Not public API
pub struct ContentDeserializer<E> {
content: Content,
+2 -1
View File
@@ -4,7 +4,8 @@ use de::{Deserialize, Deserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "collections"))]
pub use de::content::{Content, ContentRefDeserializer, ContentDeserializer, TaggedContentVisitor,
InternallyTaggedUnitVisitor, UntaggedUnitVisitor};
TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor,
UntaggedUnitVisitor};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.