-
Notifications
You must be signed in to change notification settings - Fork 254
Description
We have come across an error occurring sometimes, when we want to deserialise a configuration containing an adjecently tagged enum. The erorr occurs if the source is a string, i.e. for example coming from an environment variable.
This is a small example to reproduce:
use config::Config;
use serde::Deserialize;
#[derive(Deserialize, Debug)]
#[serde(tag = "type", content = "value")]
enum A {
V1(u64),
V2(String),
}
fn main() {
let config = Config::builder()
.add_source(config::Environment::with_prefix("APP").separator("_"))
.build()
.unwrap();
let a = config.try_deserialize::<A>().unwrap();
}Then I run this with the following environment variables:
APP_type=V1 APP_value=42 cargo run
This errors 50% of the time and runs through successfully the other 50%. The error message is:
called `Result::unwrap()` on an `Err` value: invalid type: string "42", expected u64
I debugged this and the error occurs if the value key gets stored in the internal hashmap before the type key, therefore the indeterminim stems from the indeterministic nature of the ordering in hashmaps. This might be related to #442 but I don't think a solution is to just make it deterministic. I would guess that either it is supported to parse strings into variants that store integers, or it is not, it should not depend on the ordering of the tag versus the content.
If one wants to reproduce this without environment variables one can use:
let config = Config::builder()
.set_default("type", "V1")
.unwrap()
.set_default("value", "42")
.unwrap()
.build()
.unwrap();