I have a large struct with various configuration values in it, something like:
struct Style {
foreground: f32,
background: f32,
size: [f32; 2],
...etcetcetcetc...
}
I have defined the defaults for these using Default
, like so:
impl Default for Style {
fn default() -> Self {
Self {
foreground: 0.4,
background: 0.8,
...etc...
}
}
I now want to load this from a file, allowing any of the fields to by omitted - and if they are omitted it just uses the default value.
So using serde_derive I did this:
#[derive(Deserialize, Serialize)]
struct Style {
#[serde(default)]
foreground: f32,
#[serde(default)]
background: ...
However the #[serde(default)]
annotation uses the default value of a f32 (which is 0.0), so if I load an empty document I'll get a bunch of 0.0
instead of the values from the impl Default
I'm doing something like this:
let style = if let Some(path) = cli_options.override_settings {
let s: Style = serde_whatever.load(path).unwrap();
} else {
Style::default()
};
The problem is how to define the default values once, for both the serde-loading and non-serde code paths?
Things I've thought of are:
-
#[serde(default="...")]
seems to require passing a function, which would then mean one function for each of the many struct entries which is impractical - I could define each of the
Style
entries asOption<f32>
etc. That way the default isNone
- then I can dolet mut style = Style::default();
and merge the loaded settings withstyle.update(serde_whatever.load(path));
- this would work okay, but requires wrapping everything inOption
which is wrong (as the values aren't optional, and would thus require more clutter likestyle.foreground.unwrap()
)