Skip to content

Commit

Permalink
Allow patch + patch if no conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
yanganto committed Aug 12, 2024
1 parent c0d3ff5 commit a7835b3
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 44 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ fn patch_json() {
let patch: ItemPatch = serde_json::from_str(data).unwrap();

item.apply(patch);
// You can do
// `let new_item = item << patch;`

// For multiple patches,
// you can do this
// `let new_item = item << patch_1 << patch_2;`
// or make an aggregated one, but please make sure the patch fields do not conflict, else will panic
// ```
// let overall_patch = patch_1 + patch_2 + patch_3;
// let new_item = item << overall_patch;
// ```

assert_eq!(
item,
Expand Down
61 changes: 22 additions & 39 deletions struct-patch-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,45 +125,28 @@ impl Patch {
}
}

// TODO
// We need unstable feature to make sure the type of field for add feature
// https://doc.rust-lang.org/std/any/fn.type_name_of_val.html
// impl #generics core::ops::Add<Self> for #name #generics #where_clause {
// type Output = Self;

// fn add(mut self, rhs: Self) -> Self {
// Self {
// #(
// #renamed_field_names: match (self.#renamed_field_names, rhs.#renamed_field_names) {
// (Some(a), Some(b)) => {
// if std::any::type_name_of_val(&a) == "usize" {
// Some(a + b)
// } else {
// Some(b)
// }
// },
// (Some(a), None) => Some(a),
// (None, Some(b)) => Some(b),
// (None, None) => None,
// },
// )*
// #(
// #original_field_names: match (self.#original_field_names, rhs.#original_field_names) {
// (Some(a), Some(b)) => {
// if std::any::type_name_of_val(&a) == "usize" {
// Some(a + b)
// } else {
// Some(b)
// }
// },
// (Some(a), None) => Some(a),
// (None, Some(b)) => Some(b),
// (None, None) => None,
// },
// )*
// }
// }
// }
impl #generics core::ops::Add<Self> for #name #generics #where_clause {
type Output = Self;

fn add(mut self, rhs: Self) -> Self {
Self {
#(
#renamed_field_names: match (self.#renamed_field_names, rhs.#renamed_field_names) {
(Some(a), Some(b)) => {
// TODO handle #[patch(addable)] fields
panic!("There are conflict patches in {}", stringify!(#renamed_field_names))
},
(Some(a), None) => Some(a),
(None, Some(b)) => Some(b),
(None, None) => None,
},
)*
#(
#original_field_names: rhs.#original_field_names.or(self.#original_field_names),
)*
}
}
}
};

let patch_impl = quote! {
Expand Down
18 changes: 13 additions & 5 deletions struct-patch/examples/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ fn main() {
assert_eq!(item.field_string, "");

let another_patch = ItemPatch {
field_complete: None,
field_int: None,
field_string: Some("from another patch".into()),
};

let _conflict_patch = ItemPatch {
field_complete: None,
field_int: Some(1),
field_string: Some("from another patch".into()),
Expand All @@ -38,11 +44,13 @@ fn main() {
field_string: None,
};

// TODO
// We need unstable feature to make sure the type of field for add feature
// https://doc.rust-lang.org/std/any/fn.type_name_of_val.html#
// let final_item_from_merge = item.clone() << (another_patch.clone() + the_other_patch.clone());
// assert_eq!(final_item_from_merge.field_int, 3);
// let final_item_from_merge = item.clone() << (_conflict_patch + the_other_patch.clone());
// Will get panic `There are conflict patches in field_int`
// Will be handdled as the discussion
// https://github.com/yanganto/struct-patch/pull/32#issuecomment-2283154990

let final_item_from_merge = item.clone() << (another_patch.clone() + the_other_patch.clone());
assert_eq!(final_item_from_merge.field_int, 2);

let final_item_series_patch = item << another_patch << the_other_patch;
assert_eq!(final_item_series_patch.field_int, 2);
Expand Down

0 comments on commit a7835b3

Please sign in to comment.