Open RapidPencil opened 3 months ago
There are some limitations to confik
that make this harder to avoid, but I think the actual bug is probably in serde
. E.g.
use serde::Deserialize;
#[derive(Debug, Clone, Deserialize, Default)]
struct ConfigOuter(#[serde(default)] Config);
#[derive(Debug, Clone, Deserialize, Default)]
#[serde(tag = "type", rename_all = "snake_case")]
enum Config {
Foo(Foo),
Bar(Bar),
#[default]
Unknown,
}
#[derive(Debug, Clone, Deserialize)]
struct Foo {
foo: String,
}
#[derive(Debug, Clone, Deserialize)]
struct Bar {
bar: String,
}
#[test]
fn test() {
// This fails with:
//
// ---- test stdout ----
// thread 'test' panicked at src/main.rs:27:58:
// called `Result::unwrap()` on an `Err` value: Error("missing field `type`", line: 1, column: 2)
// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
//
// However it should work and produce `ConfigOuter(Config::Unknown)`
let config: ConfigOuter = serde_json::from_str("{}").unwrap();
}
Similarity, serde(other)
also fails for your example Config
:
use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
enum Config {
Foo(Foo),
Bar(Bar),
#[serde(other)]
Unknown,
}
#[derive(Debug, Clone, Deserialize)]
struct Foo {
foo: String,
}
#[derive(Debug, Clone, Deserialize)]
struct Bar {
bar: String,
}
#[test]
fn test() {
// This fails with:
//
// ---- test stdout ----
// thread 'test' panicked at src/main.rs:27:58:
// called `Result::unwrap()` on an `Err` value: Error("missing field `type`", line: 1, column: 2)
// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
//
// However it should work and produce `Config::Unknown`
let config: Config = serde_json::from_str("{}").unwrap();
}
Say you have a serde tagged enum by
#[confik(forward_serde(tag = "type"))]
in the configuration:with
config.toml
and environment variable
The above works. However, remove either of
type = "foo"
fromconfig.toml
orTYPE=foo
from the environment, and this fails with an error: