Skip to content

Commit aadd8c8

Browse files
authored
feat: Add support for float and boolean hash keys (#650)
The `unreachable!` code at https://github.com/rust-cli/config-rs/blob/main/src/file/format/yaml.rs#L53 is reachable, and this PR fixes it for two simple types: reals and booleans. Prior to this change you'd get this error trying to parse the following: ``` thread '...' panicked at .../config-0.15.9/src/file/format/yaml.rs:53:26: internal error: entered unreachable code ``` The problematic case for me turned out to be float keys: ```yaml inner_float: 0.1: "float 0.1" 0.2: "float 0.2" ``` The change in this PR follows the same pattern as already exists for Strings and Integers - just parse them as strings and leave it up to the user to work out what to do with that. Personally I only need the Real support, so happy to remove the Boolean case if that's at all contentious. I decided not to look into whether you can craft a hash with the other Yaml types (below) because it's such an odd use case it didn't seam realistic! That said, #547 suggests that just treating Hash as string would have avoided that users' problem. However, converting from these types back into the exact string format they were parsed in would be difficult, so it's not clear what the right implementation would be. So getting the simpler case (reals, booleans) done feels like the right sized change to make. ``` Array(Array), Hash(Hash), Alias(usize), Null, BadValue, ``` Let me know what you think! And thanks for maintaining this useful crate :)
2 parents 7b2ba76 + 1ecc731 commit aadd8c8

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

src/file/format/yaml.rs

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ fn from_yaml_value(
5151
yaml::Yaml::String(k) => m.insert(k.to_owned(), from_yaml_value(uri, value)?),
5252
yaml::Yaml::Integer(k) => m.insert(k.to_string(), from_yaml_value(uri, value)?),
5353
yaml::Yaml::Boolean(k) => m.insert(k.to_string(), from_yaml_value(uri, value)?),
54+
yaml::Yaml::Real(k) => m.insert(k.to_owned(), from_yaml_value(uri, value)?),
5455
other => Err(Box::new(UnsupportedHashKeyError(format!("{other:?}"))))?,
5556
};
5657
}

tests/testsuite/file_yaml.rs

+24
Original file line numberDiff line numberDiff line change
@@ -382,3 +382,27 @@ inner_bool:
382382
assert_eq!(config.inner_bool.get(&true).unwrap(), "bool true");
383383
assert_eq!(config.inner_bool.get(&false).unwrap(), "bool false");
384384
}
385+
386+
#[test]
387+
fn test_yaml_parsing_float_hash() {
388+
#[derive(Debug, Deserialize)]
389+
struct TestStruct {
390+
inner_float: HashMap<String, String>,
391+
}
392+
393+
let config = Config::builder()
394+
.add_source(File::from_str(
395+
r#"
396+
inner_float:
397+
0.1: "float 0.1"
398+
0.2: "float 0.2"
399+
"#,
400+
FileFormat::Yaml,
401+
))
402+
.build()
403+
.unwrap()
404+
.try_deserialize::<TestStruct>()
405+
.unwrap();
406+
assert_eq!(config.inner_float.get("0.1").unwrap(), "float 0.1");
407+
assert_eq!(config.inner_float.get("0.2").unwrap(), "float 0.2");
408+
}

0 commit comments

Comments
 (0)