mehcode / config-rs

⚙️ Layered configuration system for Rust applications (with strong support for 12-factor applications).
Apache License 2.0
2.43k stars 206 forks source link

Nested arrays badly mangled #464

Closed ijackson closed 8 months ago

ijackson commented 9 months ago

To reproduce:

    #[test]
    fn list() {
        let jtxt = r#" { "proxy_ports": [ [1,2] ] } "#;
        let jval: serde_json::Value = serde_json::from_str(jtxt).unwrap();
        //dbg!(&jval);
        let jcfg = config::Config::try_from(&jval).unwrap();
        //dbg!(&jcfg);
        let jret: serde_json::Value = jcfg.clone().try_deserialize().unwrap();
        println!("json roundtrip: {jret:#?}");

        let ttxt = r#" proxy_ports = [ [1,2] ] "#;
        let tval: toml::Value = toml::from_str(ttxt).unwrap();
        //dbg!(&tval);
        let tcfg = config::Config::try_from(&tval).unwrap();
        //dbg!(&tcfg);
        let tret: Result<String, _> = tcfg.clone().try_deserialize()
            .map(|v: toml::Value| toml::to_string(&v).unwrap());
        println!("toml roundtrip: {tret:#?}");
    }

Expected output:

json roundtrip: Object {
    "proxy_ports": Array [
        Array [
            Number(1),
            Number(2),
        ],
    ],
}
toml roundtrip: Ok(
    "proxy_ports = [[1, 2]]\n"
)

Actual output:

json roundtrip: Object {
    "proxy_ports": Array [
        Null,
        Number(1),
        Number(2),
    ],
}
toml roundtrip: Err(
    invalid type: unit value, expected any valid TOML value,
)

Uncommenting the dbgs in the repro above shows this, which seems entirely wrong:

[crates/arti/src/onion_proxy.rs:143] &jcfg = Config {
    defaults: {},
    overrides: {
        Subscript(
            Identifier(
                "proxy_ports",
            ),
            1,
        ): Value {
            origin: None,
            kind: I64(
                1,
            ),
        },
        Subscript(
            Identifier(
                "proxy_ports",
            ),
            2,
        ): Value {
            origin: None,
            kind: I64(
                2,
            ),
        },
    },
    sources: [],
    cache: Value {
        origin: None,
        kind: Table(
            {
                "proxy_ports": Value {
                    origin: None,
                    kind: Array(
                        [
                            Value {
                                origin: None,
                                kind: Nil,
                            },
                            Value {
                                origin: None,
                                kind: I64(
                                    1,
                                ),
                            },
                            Value {
                                origin: None,
                                kind: I64(
                                    2,
                                ),
                            },
                        ],
                    ),
                },
            },
        ),
    },
}