Decide and implement policy on Option in config
We have some config settings that can "do the thing", or "not do it". Examples I have encountered so far are:
-
proxy.socks_port
, default 9150 -
proxy.dns_port
, default is don't -
logging.journald
, default is don't
In these cases we support a sentinel value meaning "do not do this thing". For ports, 0; for journald, ""
. This is necessary because when parsing and deserializing TOML, there is no way to explicitly specify "None". So to override a nontrivial default it is necessary to set the value to something.
I think we are more or less coherent about this at least in these three cases, at the serde (and therefore TOML) layer, but maybe not correct. The Builder
contains Option<Option<T>>
. I think this deserializes at least from TOML the same way Option<T>
, but probably we should change this to just Option<T>
.
And, our public and internal Rust APIs are confused:
-
Should we use
builer(setter(strip_option))
, so that eg we haveProxyConfig::socks_port(port: u16)
? (Some but not all of the above do that.) That expects the caller to pass0
to meanNone
which is anomalous. I propose the answer "don't usestrip_option
. -
In the validated version of the configuration, what should the type be, and how do we represent the "none" value? Should we use
Option<NonZeruU16>
for the port, say? (I say "no", because those NonZero types are a pain to work with.) ISTM that we should useOption<T>
(eg,Option<u16>
) but normalise it so that we never haveSome(<sentinel>)
. -
A question arises: is the sentinel value always going to be
T::Default
?
This is part of #458 (closed). Noticed while pursuing "test that example config is exhaustive", part of #457 (closed).