struct_merge/
lib.rs

1pub use struct_merge_codegen::*;
2
3/// Merge another struct into `Self`.
4pub trait StructMerge<Src> {
5    /// Merge the given struct into `Self` whilst consuming it.
6    fn merge(&mut self, src: Src);
7
8    /// Merge the given struct into `Self` whilst consuming it.
9    ///
10    /// Nearly the same as `merge`, but any `Self::Option<T>` fields will only get merged if the
11    /// value of the field is `None`.
12    ///
13    /// For example:
14    /// ```ignore
15    /// struct Target { a: Option<String> };
16    /// struct Src { a: String };
17    ///
18    /// let target = Target { a: Some("test".to_string()) };
19    /// let src = Src { a: "test2".to_string() };
20    ///
21    /// target.merge_soft(src);
22    /// // Value didn't get merged as `target.a` was `Some`
23    /// assert_eq!(target.a, "test".to_string());
24    /// ```
25    fn merge_soft(&mut self, src: Src);
26}
27
28/// Counterpart of [StructMerge].
29/// This will merge `Self` into a given target.
30pub trait StructMergeInto<Target: ?Sized> {
31    /// Check the [StructMerge::merge] docs.
32    fn merge_into(self, target: &mut Target);
33
34    /// Check the [StructMerge::merge_soft] docs.
35    fn merge_into_soft(self, target: &mut Target);
36}
37
38/// Implement the [StructMerge] trait for all types that provide [StructMergeInto] for it.
39impl<Target, Src: StructMergeInto<Target>> StructMerge<Src> for Target {
40    fn merge(&mut self, src: Src) {
41        src.merge_into(self);
42    }
43
44    fn merge_soft(&mut self, src: Src) {
45        src.merge_into_soft(self);
46    }
47}
48
49/// Merge another borrowed struct into `Self`.
50///
51/// All fields to be merged on the borrowed struct have to implement [Clone].
52pub trait StructMergeRef<Src> {
53    /// Merge the given struct into `Self`.
54    fn merge_ref(&mut self, src: &Src);
55
56    /// Merge the given struct into `Self`.
57    ///
58    /// Nearly the same as `merge_ref`, but any `Self::Option<T>` fields will only get merged if the
59    /// value of the field is `None`.
60    ///
61    /// For example:
62    /// ```ignore
63    /// struct Target { a: Option<String> };
64    /// struct Src { a: String };
65    ///
66    /// let target = Target { a: Some("test".to_string()) };
67    /// let src = Src { a: "test2".to_string() };
68    ///
69    /// target.merge_ref_soft(&src);
70    /// // Value didn't get merged as `target.a` was `Some`
71    /// assert_eq!(target.a, "test".to_string());
72    /// ```
73    fn merge_ref_soft(&mut self, src: &Src);
74}
75
76/// Counterpart of [StructMergeRef].
77/// This will merge `&Self` into a given target.
78pub trait StructMergeIntoRef<Target: ?Sized> {
79    /// Check the [StructMergeRef::merge_ref] docs.
80    fn merge_into_ref(&self, target: &mut Target);
81
82    /// Check the [StructMergeRef::merge_ref_soft] docs.
83    fn merge_into_ref_soft(&self, target: &mut Target);
84}
85
86/// Implement the [StructMergeRef] trait for all types that provide [StructMergeInto] for it.
87impl<Target, Src: StructMergeIntoRef<Target>> StructMergeRef<Src> for Target {
88    fn merge_ref(&mut self, src: &Src) {
89        src.merge_into_ref(self);
90    }
91
92    fn merge_ref_soft(&mut self, src: &Src) {
93        src.merge_into_ref_soft(self);
94    }
95}
96
97pub mod prelude {
98    pub use super::{StructMerge, StructMergeRef};
99}