Search code examples
rustenumsserdetoml

Rust Serialize and Deserialize toml


I'm getting a very useless error from serde.

No matter what I do I can't seem to get this toml file to be put in the structs.

My toml file:

[[list]]
host = "127.0.0.1:8080"
[[list.server_options.Static]]
dir = "somedir"
error_page = "error.html"
entry_point = "index.html"
#[derive(Deserialize, Debug)]
enum ServerOptions {
    Static {
        dir: Option<String>,
        entry_point: Option<String>,
        error_page: Option<String>,
    },
    RevProxy {
        proxy_ip: Option<String>,
    },
    None,
}

#[derive(Deserialize, Debug)]
struct Site {
    host: String,
    server_options: ServerOptions,
}

#[derive(Deserialize, Debug)]
struct Sites {
    list: Vec<Site>,
}

fn main() {
    let config_str = std::fs::read_to_string("config.toml")?;
    let config: Sites = toml::from_str(&config_str).expect("invalid config");
}

Playground.

thread 'main' panicked at 'invalid config: Error { inner: Error { inner: TomlError { message: "invalid type: map, expected a string", original: Some("[[list]]\nhost = \"127.0.0.1:8080\"\n[[list.server_options.Static]]\n#dir = \"somedir\"\n#error_page = \"error.html\"\n#entry_point = \"index.html\""), keys: ["list", "server_options"], span: Some(33..63) } } }', src/main.rs:158:55
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

when i pass the error to anyhow i get the following

Error: TOML parse error at line 3, column 1
  |
3 | [[list.server_options.Static]]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
invalid type: map, expected a string

when i try to Serialize my config i get the following error back


Err(
    Error {
        inner: UnsupportedType(
            Some(
                "ServerOptions",
            ),
        ),
    },
)

What am I missing here? are enums with value not supported ..?


Solution

  • If you want to deserialize into an enum you have to provide a table, not an array:

    [[list]]
    host = "127.0.0.1:8080"
    [list.server_options.Static]
    dir = "somedir"
    error_page = "error.html"
    entry_point = "index.html"
    

    As for serializing you can't serialize an enum using toml:

    Note that the TOML format does not support all datatypes in Rust, such as enums, tuples, and tuple structs.

    From the docs on Serializer