Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Allow YAML tags to be used to specify an enum variant. Closes #115
Browse files Browse the repository at this point in the history
  • Loading branch information
Eli Snow committed Oct 28, 2018
1 parent 4954d57 commit c0bbe1a
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 7 deletions.
33 changes: 26 additions & 7 deletions src/de.rs
Expand Up @@ -380,6 +380,7 @@ impl<'de, 'a, 'r> de::MapAccess<'de> for MapAccess<'a, 'r> {
struct EnumAccess<'a: 'r, 'r> {
de: &'r mut Deserializer<'a>,
name: &'static str,
tag: Option<&'static str>,
}

impl<'de, 'a, 'r> de::EnumAccess<'de> for EnumAccess<'a, 'r> {
Expand All @@ -405,12 +406,16 @@ impl<'de, 'a, 'r> de::EnumAccess<'de> for EnumAccess<'a, 'r> {
}
}

let variant = match *self.de.next()?.0 {
Event::Scalar(ref s, _, _) => &**s,
_ => {
*self.de.pos -= 1;
let bad = BadKey { name: self.name };
return Err(de::Deserializer::deserialize_any(&mut *self.de, bad).unwrap_err());
let variant = if let Some(tag) = self.tag {
tag
} else {
match *self.de.next()?.0 {
Event::Scalar(ref s, _, _) => &**s,
_ => {
*self.de.pos -= 1;
let bad = BadKey { name: self.name };
return Err(de::Deserializer::deserialize_any(&mut *self.de, bad).unwrap_err());
}
}
};

Expand Down Expand Up @@ -938,12 +943,26 @@ impl<'de, 'a, 'r> de::Deserializer<'de> for &'r mut Deserializer<'a> {
self.jump(&mut pos)?
.deserialize_enum(name, variants, visitor)
}
Event::Scalar(_, _, _) => visitor.visit_enum(UnitVariantAccess { de: self }),
Event::Scalar(_, _, ref t) => {
if let Some(TokenType::Tag(ref handle, ref suffix)) = t {
if handle == "!" {
if let Some(tag) = variants.iter().find(|v| *v == suffix) {
return visitor.visit_enum(EnumAccess {
de: self,
name: name,
tag: Some(tag),
});
}
}
}
visitor.visit_enum(UnitVariantAccess { de: self })
},
Event::MappingStart => {
*self.pos += 1;
let value = visitor.visit_enum(EnumAccess {
de: self,
name: name,
tag: None,
})?;
self.end_mapping(1)?;
Ok(value)
Expand Down
25 changes: 25 additions & 0 deletions tests/test_de.rs
Expand Up @@ -162,6 +162,31 @@ fn test_enum_alias() {
test_de(&yaml, &expected);
}

#[test]
fn test_enum_tag() {
#[derive(Deserialize, PartialEq, Debug)]
enum E {
A(String),
B(String),
}
#[derive(Deserialize, PartialEq, Debug)]
struct Data {
a: E,
b: E,
}
let yaml = unindent(
"
---
a: !A foo
b: !B bar"
);
let expected = Data {
a: E::A("foo".into()),
b: E::B("bar".into()),
};
test_de(&yaml, &expected);
}

#[test]
fn test_number_as_string() {
#[derive(Deserialize, PartialEq, Debug)]
Expand Down

0 comments on commit c0bbe1a

Please sign in to comment.