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 pass0to meanNonewhich 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).