cthu
cthu

Reputation: 21

How to catch-all tables in TOML file with toml-rs library in Rust

New to Rust! Currently, I am playing around with toml-rs library to read TOML configuration.

See my code on Rust Playground

Here's code that I took from toml-rs' examples/decode.rs and updated the code

use serde::Deserialize;
use toml;

#[derive(Debug, Deserialize)]
struct Config {
    active_users: Vec<String>,
    // john: Option<User>, - i don't want to manually add each line for all tables
}

#[derive(Debug, Deserialize)]
struct User {
    name: String,
}

fn main() {
    let toml_str = r#"
        active_users = ["john", "new2rust"]
        
        [john]
        name = "John Doe"
        
        [new2rust]
        name = "Jane Doe"
        
        [randomguy]
        name = "Rust Guy"
    "#;

    let decoded: Config = toml::from_str(toml_str).unwrap();
    println!("{:#?}", decoded);
}

output

Config {
    active_users: [
        "john",
        "new2rust",
    ],
}

My desired output would be like this

Config {
    active_users: [
        "john",
        "new2rust",
    ],
    john: ...,
    new2rust: ...,
    randomguy: ...,
}

I don't want to manually add each line john: Option<User> to Config for all other tables since configuration will be updated frequently. So I am not sure how to catch all tables and add them to Config with toml-rs.

Upvotes: 2

Views: 716

Answers (1)

SeedyROM
SeedyROM

Reputation: 2451

There's definitely a way to do what you're describing, but it's not necessary, and not a good idea.

Like mentioned in the comments, you're basically hardcoding your users because of them being their own fields in the struct. Instead of misusing the rest of the tables in the file you should use an array of tables (https://toml.io/en/v1.0.0#array-of-tables).

As also mentioned you can use serde's flatten, but that's not what you want and honestly just going to lead you down the wrong road while trying to learn Rust.

Then your markup would look like this:

active_users = [ { name = "john" }, { name = "new2rust" } ]

And your deserialization structs would look like this:

#[derive(Debug, Deserialize)]
struct User {
    name: String,
}

#[derive(Debug, Deserialize)]
struct Config {
    active_users: Vec<User>,
}

Upvotes: 1

Related Questions