NetParams: Document its role as a validated config parameter
In #413 (closed) and a code comment, I grumbled about NetParams
. Having investigated, my conclusions are as follows.
Facts
-
NetParams<T>
has as its primary use in elements of the state of the dirmgr, tor-netdoc, etc. There are at least two specialisations and various places where this data appears. - tor-dirmgr takes a config setting for allowing the config to override some network parameters - network parameters that it handles internally as a
NetParams<i32>
. For convenience of the code there, it just reuses theNetParams<i32>
as the built (validated) config element.DirMgrConfig
is not a builder struct (for reasons explained in its comments); instead, it is simply a copy of some of the pieces of aTorClientConfig
. - Therefore, a validated
TorClientConfig
containsoverride_net_params: NetParams<i32>
. - derive_builder attrs are used to hide all this in the
TorClientConfigBuilder
. The builder (the public API) contains a plainHashMap
and offers anoverride_net_params()
mut accessor function.
So the NetParams
is already not exposed in the primary config API - only in lower levels. The primary config API is precisely to allow the user to build and manipulate a HashMap<String,i32>
. Likewise, we deserialise it as a HashMap
defaulting to empty.
Offering a concrete struct in this way is roughly in line with what we now do for lists, where we offer accessors for a Vec
. However, there is a difference: the Vec
arrangements are capable of having a non-empty default. Here, the semantics of the setting imply that it has an empty default.
Choices for the top-level API
Overall I think the choices for the top-level config API here are:
-
As things are now. Expose a
HashMap
directly, with no_opt
etc. (ie no non-empty defaulting). If we want to add config entries in the future which are of this rough shape but with a non-empty default, they might need a more sophisticated API. However, the current API mirrors the one forVec
s pretty precisely, so I think that future change would be an extension even if we were to retrofit it tooverride_net_params
. -
Build, now, a thing for
HashMap
that mirrors the list builder forVec
. This seems unattractive at this stage, particularly since I think that API would be a superset of what we have now. -
Make the builder have a
Vec
and offer the list API, even though this is actually a non-ordered set of overrides (or, rather, a set of overrides which honours ordering only in that it forgets earlier settings). This seems quite unattractive, as it would be a misrepresentation of the semantics. And it would either have to beVec<(String, Option<i32>)>
so that it can support deletion by appending, or deletion would have to be done by filtering even though overriding can be done by appending. -
As we have now, but hide the
HashMap
behind something with a less rich API. There is an argument for this - our reasoning forVec
was thatVec
is a very fundamental type in Rust, and this is less so forHashMap
. Nevertheless I don't foresee us wanting to change this.
Of these I prefer (1), the status quo. (2) and (3) are quite unattractive.
NetParams
as both state and validated config
Finally, it is sligbhtly anomalous that NetParams<i32>
is both a piece of state and a piece of config. But this is in the lower layers and I don't see any value in separating these types - it would just lead to pointless conversion code. I think comments are fine to address this.
We could add type aliases (eg type NetParamsBuilder<T> = HashMap<String,T>
, but IMO they would confuse and indirect more than they would enlighten.
Disposition
Therefore I proose here to address #413 (closed) in code comments, and make no other code changes.
Would the reviewer please double check my reasoning above :-). If I have got anything wrong, or you disagree with this resolution, we should talk about it and not merge this MR.