pub trait Patch<P> {
// Required methods
fn apply(&mut self, patch: P);
fn into_patch(self) -> P;
fn into_patch_by_diff(self, previous_struct: Self) -> P;
fn new_empty_patch() -> P;
}Expand description
A struct that a patch can be applied to
Deriving Patch will generate a patch struct and an accompanying trait impl so that it can be applied to the original struct.
#[derive(Patch)]
struct Item {
field_bool: bool,
field_int: usize,
field_string: String,
}
// Generated struct
// struct ItemPatch {
// field_bool: Option<bool>,
// field_int: Option<usize>,
// field_string: Option<String>,
// }§Container attributes
§#[patch(attribute(derive(...)))]
Use this attribute to derive traits on the generated patch struct
#[derive(Patch)]
#[patch(attribute(derive(Debug, Default, Deserialize, Serialize)))]
struct Item;
// Generated struct
// #[derive(Debug, Default, Deserialize, Serialize)]
// struct ItemPatch {}§#[patch(attribute(...))]
Use this attribute to pass the attributes on the generated patch struct
// This example need `serde` and `serde_with` crates
#[derive(Patch, Debug)]
#[patch(attribute(derive(Serialize, Deserialize, Default)))]
#[patch(attribute(skip_serializing_none))]
struct Item;
// Generated struct
// #[derive(Default, Deserialize, Serialize)]
// #[skip_serializing_none]
// struct ItemPatch {}§#[patch(name = "...")]
Use this attribute to change the name of the generated patch struct
#[derive(Patch)]
#[patch(name = "ItemOverlay")]
struct Item { }
// Generated struct
// struct ItemOverlay {}§Field attributes
§#[patch(skip)]
If you want certain fields to be unpatchable, you can let the derive macro skip certain fields when creating the patch struct
#[derive(Patch)]
struct Item {
#[patch(skip)]
id: String,
data: String,
}
// Generated struct
// struct ItemPatch {
// data: Option<String>,
// }§#[patch(skip_wrap)]
Keep the field type as-is in the generated patch struct (no extra Option
wrapping). This is useful for fields that are already Option<...>,
typically Option<Vec<_>>, where the default double-Option in the patch
is unwanted. With skip_wrap, None in the patch means “no change” and
Some(v) sets the field to Some(v) (including Some(vec![]) to clear
the vector). Cannot be combined with empty_value.
#[derive(Default, Patch)]
struct Item {
#[patch(skip_wrap)]
tags: Option<Vec<String>>,
}
// Generated struct
// struct ItemPatch {
// tags: Option<Vec<String>>, // not wrapped again
// }
let mut item = Item { tags: Some(vec!["a".into()]) };
// `None` in the patch keeps the field unchanged.
item.apply(ItemPatch { tags: None });
assert_eq!(item.tags, Some(vec!["a".into()]));
// `Some(vec![])` still applies and clears the list.
item.apply(ItemPatch { tags: Some(vec![]) });
assert_eq!(item.tags, Some(vec![]));Required Methods§
Sourcefn into_patch(self) -> P
fn into_patch(self) -> P
Returns a patch that when applied turns any struct of the same type into Self
Sourcefn into_patch_by_diff(self, previous_struct: Self) -> P
fn into_patch_by_diff(self, previous_struct: Self) -> P
Returns a patch that when applied turns previous_struct into Self
Sourcefn new_empty_patch() -> P
fn new_empty_patch() -> P
Get an empty patch instance
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".