Simplify config API types and accessors, and config handling code
For each FooConfig:
- Make
FooConfigBuilderSerialize and Deserialize; - Make the validated configuration no longer Serialize and Deserialize
-
Make;FooConfigthe builder type -
Have the validated configuration be a hidden type that is created when passing theSadly this is not going to be possible, since the validated type must be convyed through the various API layers so that the builders can work.FooConfigto a constructor. MakeFooConfig::validatepub, while havingFooConfig::buildbe private.
Improve cases where BigConfig contains a LittleConfig.
- Automatically generate the code to convert and validate
LittleConfigtoLittleConfigValidatedand put it intoBigConfigValidated.little. (This is necessary for the above changes becauseBigConfigValidated.littlemust beLittleConfigValidated, but the builder must contain aLittleConfignot aLittleConfigValidated.) - Instead of providing a setter method on
BigConfigthat expects to consume aLittleConfig, provide an accessor methodimpl BigConfig { pub fn little(&mut self) -> &mut LittleConfig; }. [1]
This should considerably reduce the amount of code in our tree, although it requires new feature(s) in derive_builder.
[1] Rationale: this allows the caller to set a sub-field big.little.wombat by writing bit.little().wombat(Wombat) rather than making an entirely new LittleConfig. The latter is clumsy and also risks accidental overwrites if different parts of the calling code want to modify different fields of big.little. (If we move fields out of little, API could be preserved by making LittleConfig a newtype with appropriate handwritten accessors which redirect the field accessors.)
This is part of #285 (closed).
Edited by Ian Jackson