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

Unreachable code fault at config-0.14.0/src/file/format/yaml.rs:53:26 #547

Open mjaakkol opened 3 months ago

mjaakkol commented 3 months ago

I'm getting above error as

thread 'XXX' panicked at /home/username/.cargo/registry/src/index.crates.io-6f17d22bba15001f/config-0.14.0/src/file/format/yaml.rs:53:26:
internal error: entered unreachable code

Yaml file looks like

link:
  null:
    name: "null"
  tcp:
    address: "localhost:1234"

My structure definitions for the section are:

#[derive(serde::Deserialize, Clone)]
pub struct LinkSettings {
    pub serial: Option<SerialSettings>,
    pub unix: Option<UnixSettings>,
    pub null: Option<NullSettings>,
    pub tcp: Option<TcpSettings>,
}

#[derive(serde::Deserialize, Clone)]
pub struct NullSettings {
    pub name: String,
}

#[derive(serde::Deserialize, Clone)]
pub struct UnixSettings {
    pub name: String,
}

#[derive(serde::Deserialize, Clone)]
pub struct TcpSettings {
    pub address: String,
}

I believe above is valid yaml (not the best looking yaml but I'll add more things to the hashtable later so the structure is needed. This worked with 0.13.x

goingforbrooke commented 3 months ago

Confirmed. Thanks for the Issue @mjaakkol! 🙏🏻

Seems like the mixture of string and integer in `"localhost:1234" is unexpected.

Backtrace:

   3: config::file::format::yaml::from_yaml_value
             at ./src/file/format/yaml.rs:53:26

Assumed SerialSettings is:

#[derive(serde::Deserialize, Clone)]
pub struct SerialSettings {
    pub name: String,
}
goingforbrooke commented 3 months ago

Nevermind-- the underlying YAML library is "guessing" that localhost:1234 is a hash. I'll look into making ours "guess" better.

    match *value {
...
yaml::Yaml::Integer(value) => Ok(Value::new(uri, ValueKind::I64(value))),
        yaml::Yaml::Boolean(value) => Ok(Value::new(uri, ValueKind::Boolean(value))),
        yaml::Yaml::Hash(ref table) => {
            let mut m = Map::new();
            for (key, value) in table {
                match key {
                    yaml::Yaml::String(k) => m.insert(k.to_owned(), from_yaml_value(uri, value)?),
                    yaml::Yaml::Integer(k) => m.insert(k.to_string(), from_yaml_value(uri, value)?),
                    _ => {
                        println!("yaml::Yaml::{:?}", key);
                        unreachable!()

@mjaakkol if you want a quick fix, then separate localhost and 1234. 🩹