struct_patch/
traits.rs

1/// A struct that a patch can be applied to
2///
3/// Deriving [`Patch`] will generate a patch struct and an accompanying trait impl so that it can be applied to the original struct.
4/// ```rust
5/// # use struct_patch::Patch;
6/// #[derive(Patch)]
7/// struct Item {
8///     field_bool: bool,
9///     field_int: usize,
10///     field_string: String,
11/// }
12///
13/// // Generated struct
14/// // struct ItemPatch {
15/// //     field_bool: Option<bool>,
16/// //     field_int: Option<usize>,
17/// //     field_string: Option<String>,
18/// // }
19/// ```
20/// ## Container attributes
21/// ### `#[patch(attribute(derive(...)))]`
22/// Use this attribute to derive traits on the generated patch struct
23/// ```rust
24/// # use struct_patch::Patch;
25/// # use serde::{Serialize, Deserialize};
26/// #[derive(Patch)]
27/// #[patch(attribute(derive(Debug, Default, Deserialize, Serialize)))]
28/// struct Item;
29///
30/// // Generated struct
31/// // #[derive(Debug, Default, Deserialize, Serialize)]
32/// // struct ItemPatch {}
33/// ```
34///
35/// ### `#[patch(attribute(...))]`
36/// Use this attribute to pass the attributes on the generated patch struct
37/// ```compile_fail
38/// // This example need `serde` and `serde_with` crates
39/// # use struct_patch::Patch;
40/// #[derive(Patch, Debug)]
41/// #[patch(attribute(derive(Serialize, Deserialize, Default)))]
42/// #[patch(attribute(skip_serializing_none))]
43/// struct Item;
44///
45/// // Generated struct
46/// // #[derive(Default, Deserialize, Serialize)]
47/// // #[skip_serializing_none]
48/// // struct ItemPatch {}
49/// ```
50///
51/// ### `#[patch(name = "...")]`
52/// Use this attribute to change the name of the generated patch struct
53/// ```rust
54/// # use struct_patch::Patch;
55/// #[derive(Patch)]
56/// #[patch(name = "ItemOverlay")]
57/// struct Item { }
58///
59/// // Generated struct
60/// // struct ItemOverlay {}
61/// ```
62///
63/// ## Field attributes
64/// ### `#[patch(skip)]`
65/// If you want certain fields to be unpatchable, you can let the derive macro skip certain fields when creating the patch struct
66/// ```rust
67/// # use struct_patch::Patch;
68/// #[derive(Patch)]
69/// struct Item {
70///     #[patch(skip)]
71///     id: String,
72///     data: String,
73/// }
74///
75/// // Generated struct
76/// // struct ItemPatch {
77/// //     data: Option<String>,
78/// // }
79/// ```
80pub trait Patch<P> {
81    /// Apply a patch
82    fn apply(&mut self, patch: P);
83
84    /// Returns a patch that when applied turns any struct of the same type into `Self`
85    fn into_patch(self) -> P;
86
87    /// Returns a patch that when applied turns `previous_struct` into `Self`
88    fn into_patch_by_diff(self, previous_struct: Self) -> P;
89
90    /// Get an empty patch instance
91    fn new_empty_patch() -> P;
92}
93
94pub trait Filler<F> {
95    /// Apply a filler
96    fn apply(&mut self, filler: F);
97
98    /// Get an empty filler instance
99    fn new_empty_filler() -> F;
100}
101
102#[cfg(feature = "status")]
103/// A patch struct with extra status information
104pub trait Status {
105    /// Returns `true` if all fields are `None`, `false` otherwise.
106    fn is_empty(&self) -> bool;
107}
108
109#[cfg(feature = "merge")]
110/// A patch struct that can be merged to another one
111pub trait Merge {
112    fn merge(self, other: Self) -> Self;
113}