#[derive(Merge)]
{
// Attributes available to this derive:
#[partial]
#[strategy]
}
Expand description
Automatically implements Merge for a given structure.
This derive will create a near-identical partial version of the structure with each field being optional. For example:
// Deriving `Merge` on this struct...
#[derive(Merge)]
#[partial(PartialConfig)]
struct Config {
name: String,
version: u32,
dependencies: Vec<String>,
}// ...will create this struct as well.
struct PartialConfig {
name: Option<String>,
version: Option<u32>,
dependencies: Option<Vec<String>>,
}§Attributes
-
#[partial(Name)],#[partial(Name, ...)](struct)What: This specifies the name of the partial struct generated, as well as any attributes that should be applied to the partial struct.
Where: This should annotate the struct itself.
How: The name should be a single identifier inside the parenthesis, and is commonly prefixed with “Partial”. Attributes to be applied to the partial struct may optionally be specified after name, separated by commas.
Required
-
#[partial(...)](field)What: This specifies attributes that should annotate fields within the partial struct.
Where: This should annotate fields within the struct.
How: This accepts a comma-separated list of attributes to be applied to the partial’s field inside the parenthesis. At least one attribute is required.
Optional
-
#[strategy(overwrite | merge)](field)What: This specifies how this field should be merged.
Where: This should annotate the struct’s fields.
How: The value should either be
overwriteormergein parenthesis.overwritewill replace the base’s field with the partial’s if it exists, whilemergewill use the field type’sMergeimplementation to combine the two values together.Optional: Fields without this attribute default to
overwrite.
§Examples
#[derive(Merge)]
// Name the partial version of this type `PartialConfig`.
#[partial(PartialConfig)]
struct Config {
// This field will be overwritten when merged. `#[strategy(overwrite)]` may be omitted.
#[strategy(overwrite)]
name: String,
// This field will also be overwritten when merged.
version: u32,
// This field will be combined when merged.
#[strategy(merge)]
dependencies: Vec<String>,
}Struct and field attributes can be applied to the partial struct using the #[partial(...)]
attribute. This is commonly used to implement Default for the partial struct, as its fields
are all Option<T>s.
#[derive(Merge)]
// Implement `Default` for the partial struct.
#[partial(PartialFish, derive(Default))]
struct Fish {
fins: u8,
memory: f32,
leashed: bool,
}#[derive(Merge)]
// Implement `Deserialize` for the partial struct, denying unknown fields.
#[partial(PartialConfig, derive(Deserialize), serde(deny_unknown_fields))]
struct Config {
name: String,
// When deserializing the partial struct, accept the value of either "version" or "v" for
// this field.
#[partial(serde(alias = "v"))]
version: u32,
}Be warned that the fields of partial structs are all Option<T>s. This may make certain
attributes like #[serde(default)] behave differently.
#[derive(Merge)]
#[partial(PartialTrickyDefault, derive(Deserialize))]
struct TrickyDefault {
// This attribute actually gets applied to a field like `value: Option<u64>`. Because of
// this, the default value will be `None` and not 0.
#[partial(serde(default))]
tricky_value: u64,
// This fixes the issue by making the partial field default to `Some(0)`. Much better!
#[partial(serde(default = "zero_default"))]
corrected_value: u64,
}
fn zero_default() -> Option<u64> {
Some(0)
}Simple generics are supported, however only generic types that can merge with themselves can
be annotated with #[strategy(merge)].
#[derive(Merge)]
#[partial(PartialNamedData)]
struct NamedData<T> {
name: String,
data: T,
}#[derive(Merge)]
#[partial(PartialNamedData)]
// `T: Merge<T>` means any type that can be merged with itself.
struct NamedData<T: Merge<T>>
{
name: String,
#[strategy(merge)]
data: T,
}Unit structs can also derive Merge, however there is little point in doing so.
#[derive(Merge)]
#[partial(PartialConfig)]
struct Config;§Errors
This macro only works on named structs. Enums, unions, or tuple structs will not compile.
#[derive(Merge)]
#[partial(PartialChoice)]
enum Choice {
A,
B,
}#[derive(Merge)]
#[partial(PartialConfig)]
struct Config(bool, u8, Vec<String>);This macro requires a single #[partial(...)] attribute on the struct itself.
#[derive(Merge)]
// Missing `#[partial(...)]`.
struct Config {
name: String,
dependencies: Vec<String>,
}#[derive(Merge)]
// Too many `#[partial(...)]`s.
#[partial(PartialConfig1)]
#[partial(PartialConfig2)]
struct Config {
name: String,
dependencies: Vec<String>,
}This macro only supports the overwrite and merge strategies.
#[derive(Merge)]
#[partial(PartialDog)]
struct Dog {
name: String,
// `add` is not a valid strategy.
#[strategy(add)]
age: u16,
}