From bdb3390f72dbb95ed2fd474a219a25149e0e3d7e Mon Sep 17 00:00:00 2001 From: simonsan <14062932+simonsan@users.noreply.github.com> Date: Tue, 19 Nov 2024 23:25:22 +0100 Subject: [PATCH 1/2] feat: add MergeFrom trait to conflate This adds a `MergeFrom` trait to the `conflate` crate. This trait is used to merge two values of the same type, and creates a new value that is the result of the merge. The `MergeFrom` trait is implemented for all types that implement the `Merge` trait. Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com> --- crates/conflate/src/lib.rs | 124 +++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/crates/conflate/src/lib.rs b/crates/conflate/src/lib.rs index 2a1a2f4..9034e9a 100644 --- a/crates/conflate/src/lib.rs +++ b/crates/conflate/src/lib.rs @@ -128,11 +128,13 @@ pub mod vec; /// s: "some ignored value".to_owned(), /// flag: false, /// }; +/// /// val.merge(S { /// option: Some(42), /// s: "some other ignored value".to_owned(), /// flag: true, /// }); +/// /// assert_eq!(S { /// option: Some(42), /// s: "some ignored value".to_owned(), @@ -158,11 +160,13 @@ pub mod vec; /// option2: Some(1), /// option3: None, /// }; +/// /// val.merge(S { /// option1: Some(2), /// option2: Some(2), /// option3: None, /// }); +/// /// assert_eq!(S { /// option1: Some(2), /// option2: Some(1), @@ -173,3 +177,123 @@ pub trait Merge { /// Merge another object into this object. fn merge(&mut self, other: Self); } + +/// A trait for objects that can be merged from another object +/// of the same type creating a new object. +/// +/// Using a builder like pattern to merge two objects +/// with the `option::overwrite_none` strategy. +/// +/// ``` +/// use conflate::{Merge, MergeFrom}; +/// +/// #[derive(Debug, PartialEq, Merge)] +/// #[merge(strategy = conflate::option::overwrite_none)] +/// struct S { +/// option1: Option, +/// option2: Option, +/// option3: Option, +/// option4: Option, +/// } +/// +/// let cli = S { +/// option1: None, +/// option2: Some(1), +/// option3: None, +/// option4: None, +/// }; +/// +/// let config = S { +/// option1: Some(2), +/// option2: Some(2), +/// option3: None, +/// option4: None, +/// }; +/// +/// impl Default for S { +/// fn default() -> Self { +/// S { +/// option1: None, +/// option2: None, +/// option3: Some(4), +/// option4: None, +/// } +/// } +/// } +/// +/// let val = cli +/// .merge_from(config) +/// .merge_from(S::default()); +/// +/// assert_eq!(S { +/// option1: Some(2), +/// option2: Some(1), +/// option3: Some(4), +/// option4: None, +/// }, val); +/// ``` +/// +/// Using a builder like pattern to merge two objects +/// with the `option::overwrite_some` strategy. +/// +/// ``` +/// use conflate::{Merge, MergeFrom}; +/// +/// #[derive(Debug, PartialEq, Merge)] +/// #[merge(strategy = conflate::option::overwrite_some)] +/// struct S { +/// option1: Option, +/// option2: Option, +/// option3: Option, +/// option4: Option, +/// } +/// +/// impl Default for S { +/// fn default() -> Self { +/// S { +/// option1: None, +/// option2: None, +/// option3: Some(4), +/// option4: None, +/// } +/// } +/// } +/// +/// let config = S { +/// option1: Some(2), +/// option2: Some(2), +/// option3: None, +/// option4: None, +/// }; +/// +/// let cli = S { +/// option1: None, +/// option2: Some(1), +/// option3: None, +/// option4: None, +/// }; +/// +/// let val = S::default() +/// .merge_from(config) +/// .merge_from(cli); +/// +/// assert_eq!(S { +/// option1: Some(2), +/// option2: Some(1), +/// option3: Some(4), +/// option4: None, +/// }, val); +/// ``` +pub trait MergeFrom: Merge { + /// Merge two objects into a new object. + fn merge_from(mut self, other: Self) -> Self + where + Self: Sized, + { + self.merge(other); + self + } +} + +// Blanket implementation for all types that implement `Merge`. +impl MergeFrom for T {} From 228284d0fb0b6ae6bd13319a548b17dcee7e59d2 Mon Sep 17 00:00:00 2001 From: simonsan <14062932+simonsan@users.noreply.github.com> Date: Wed, 20 Nov 2024 00:34:25 +0100 Subject: [PATCH 2/2] docs: update documentation to reflect correct overwrite strategy name Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com> --- crates/conflate/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/conflate/src/lib.rs b/crates/conflate/src/lib.rs index 9034e9a..589c4f6 100644 --- a/crates/conflate/src/lib.rs +++ b/crates/conflate/src/lib.rs @@ -234,13 +234,13 @@ pub trait Merge { /// ``` /// /// Using a builder like pattern to merge two objects -/// with the `option::overwrite_some` strategy. +/// with the `option::overwrite_with_some` strategy. /// /// ``` /// use conflate::{Merge, MergeFrom}; /// /// #[derive(Debug, PartialEq, Merge)] -/// #[merge(strategy = conflate::option::overwrite_some)] +/// #[merge(strategy = conflate::option::overwrite_with_some)] /// struct S { /// option1: Option, /// option2: Option,