Skip to content

Commit

Permalink
Recognize some enums in 'Value' deserialize.
Browse files Browse the repository at this point in the history
Resolves #91.
  • Loading branch information
SergioBenitez committed Jan 17, 2024
1 parent e8f1f13 commit 7cce6fc
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 5 deletions.
15 changes: 10 additions & 5 deletions src/value/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::cell::Cell;

use serde::Deserialize;
use serde::de::{self, Deserializer, IntoDeserializer};
use serde::de::{Visitor, SeqAccess, MapAccess};
use serde::de::{Visitor, SeqAccess, MapAccess, VariantAccess};

use crate::Figment;
use crate::error::{Error, Kind, Result};
Expand Down Expand Up @@ -396,7 +396,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
type Value = Value;

fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("a config value")
f.write_str("any valid figment value")
}

visit_fn!(visit_bool: bool => Value::Bool);
Expand Down Expand Up @@ -438,11 +438,11 @@ impl<'de> Visitor<'de> for ValueVisitor {
let mut raw_val: Option<RawValue> = None;
while let Some(key) = map.next_key()? {
if key == Value::FIELDS[0] {
id = Some(map.next_value().expect("value for key"));
id = Some(map.next_value()?);
} else if key == Value::FIELDS[1] {
raw_val = Some(map.next_value().expect("value for key"));
raw_val = Some(map.next_value()?);
} else {
dict.insert(key, map.next_value().expect("value for key"));
dict.insert(key, map.next_value()?);
}
}

Expand All @@ -457,6 +457,11 @@ impl<'de> Visitor<'de> for ValueVisitor {
Ok(dict.into())
}

fn visit_enum<A: de::EnumAccess<'de>>(self, data: A) -> result::Result<Self::Value, A::Error> {
let (tag, variant) = data.variant::<String>()?;
Ok(crate::util::nest(&tag, variant.newtype_variant()?))
}

fn visit_none<E: de::Error>(self) -> result::Result<Self::Value, E> {
Ok(Empty::None.into())
}
Expand Down
57 changes: 57 additions & 0 deletions tests/yaml-enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use serde::Deserialize;
use figment::{Figment, providers::{Format, Yaml}};

#[derive(Deserialize, PartialEq, Debug, Clone)]
pub enum Trigger {
Start,
Inter { sec: u32 },
Triple(usize, usize, usize),
End(String),
}

#[derive(Deserialize, Debug, Clone)]
pub struct Script {
pub triggers: Vec<Trigger>,
}

const YAML: &str = "
triggers:
- !Start
- !Inter
sec: 5
- !Inter { sec: 7, }
- !Triple [1, 2, 3]
- !End Now
";

const YAML2: &str = "
triggers:
- Start:
- Inter:
sec: 5
- !Inter { sec: 7, }
- Triple:
- 1
- 2
- 3
- End: Now
";

#[test]
fn figment_yaml_deserize() {
let figment = Figment::new().merge(Yaml::string(YAML));
let script = figment.extract::<Script>().unwrap();
assert_eq!(script.triggers[0], Trigger::Start);
assert_eq!(script.triggers[1], Trigger::Inter { sec: 5 });
assert_eq!(script.triggers[2], Trigger::Inter { sec: 7 });
assert_eq!(script.triggers[3], Trigger::Triple(1, 2, 3));
assert_eq!(script.triggers[4], Trigger::End("Now".into()));

let figment = Figment::new().merge(Yaml::string(YAML2));
let script = figment.extract::<Script>().unwrap();
assert_eq!(script.triggers[0], Trigger::Start);
assert_eq!(script.triggers[1], Trigger::Inter { sec: 5 });
assert_eq!(script.triggers[2], Trigger::Inter { sec: 7 });
assert_eq!(script.triggers[3], Trigger::Triple(1, 2, 3));
assert_eq!(script.triggers[4], Trigger::End("Now".into()));
}

0 comments on commit 7cce6fc

Please sign in to comment.