Sometimes you want users to be able to define in their configuration how a certain option should merge with existing values.
For example, if I have:
#[derive(Config)]
struct MyConfig {
#[setting(nested, merge = schematic::merge::replace)]
items: Vec<Item>,
}
I want the user to be able to determine how two MyConfig::items values should be merged by Schematic instead of hard-coding it to replace.
One solution I had in mind was to allow deserializing a wrapper enum, where one deserializes from a regular Vec, or from an object that includes the merge strategy:
#[derive(Config)]
struct MyConfig {
#[setting(nested)]
items: ReplaceOrMergedVec<Item>,
}
#[derive(Serialize, Deserialize, Config)]
#[serde(untagged)]
pub enum ReplaceOrMergedVec<T: Config> {
#[setting(nested, merge = schematic::merge::replace)]
Replace(Vec<T>),
#[setting(merge = merge_vec_with_strategy)]
Merged(MergedVec<T>),
}
#[derive(Serialize, Deserialize)]
pub struct MergedVec<T: Config> {
strategy: Strategy,
items: Vec<T>
}
#[derive(Serialize, Deserialize)]
pub enum Strategy {
Append,
Prepend,
Replace,
}
fn merge_vec_with_strategy<T: Config>(
mut prev: MergedVec<T>,
next: MergedVec<T>,
context: &(),
) -> MergeResult<MergedVec<T>> {
match prev.strategy {
// ...
}
}
I ran into two issues with this:
- It looks like Schematic does not support generic types on configuration structs.
- You cannot define the
merge proc-macro attribute on a nested non-collection item in a struct.
I can work around (1) by not using generics here (although it would definitely be nice), but that second feature is required because you need access to the strategy value do know how to merge the items.
I understand that there's the possibility of using Context for this, but it's not closely tied to specific fields of the configuration struct(s), and also would not be set through the configuration files themselves, so it's not really suitable for this use-case.
Any thoughts on supporting these two features, or perhaps supporting user-defined merge strategies differently?
Sometimes you want users to be able to define in their configuration how a certain option should merge with existing values.
For example, if I have:
I want the user to be able to determine how two
MyConfig::itemsvalues should be merged by Schematic instead of hard-coding it toreplace.One solution I had in mind was to allow deserializing a wrapper enum, where one deserializes from a regular
Vec, or from an object that includes the merge strategy:I ran into two issues with this:
mergeproc-macro attribute on anestednon-collection item in a struct.I can work around (1) by not using generics here (although it would definitely be nice), but that second feature is required because you need access to the
strategyvalue do know how to merge theitems.I understand that there's the possibility of using
Contextfor this, but it's not closely tied to specific fields of the configuration struct(s), and also would not be set through the configuration files themselves, so it's not really suitable for this use-case.Any thoughts on supporting these two features, or perhaps supporting user-defined merge strategies differently?