Dealing with `Options` and defaults when parsing in TOML structs with Rust+Serde
Asked Answered
W

0

6

I have been working on configuration parsing code and wondered if you could help me to pick the best types for this code.

I am trying to parse the following TOML:

[default]
a=10
b="abc"

[section1]
a = 78

[section2]
b="xyz"

The types of keys are the same in each section and each field follows the chain of defaults: sectionX.value => default.value => default value hardcoded in Rust via x.value.or(default.value).or(Some(...) for each field.

The most straightforward way to declare it in Rust (including serde attributes)

struct Section{
   a: Option<usize>,
   b: Option<String>,
}

The problem is that I want to parse all defaults first, and then use a fully materialized struct with no unassigned values in my code.

struct Section{
   a: usize,
   b: String,
}

I can use the following approaches:

  1. Use original Section struct and always to unwrap/expect because I "know" the defaults have been assigned in the config parsing code. I make a mistake, I can catch panic and that does not look tidy. I'd like to leverage more help from the compiler.

  2. Use the second Section struct (the one that has no Options). I can assign defaults via Serde annotations, but then I am loosing the signal that something was unspecified and needs a default from another level.

  3. Declare both variants of the struct. This is the most verbose variant and I will look even more verbose when I grow 20+ fields or embedded structs in the config.

  4. Generated Solution 3 via macros or some clever typing. Is there a crate for this? Maybe Section could have some generic type that can be Option in one place, but then "newtype" wrapper with a single value somewhere else?

  5. Something else?

Some of the solutions above would work alright, but maybe there is a known elegant solution.

Willdon answered 20/11, 2022 at 14:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.