Skip to content

Commit 6f1943b

Browse files
committed
add feature to generate setters in the Difference proc macro
1 parent eda682c commit 6f1943b

File tree

12 files changed

+415
-25
lines changed

12 files changed

+415
-25
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "structdiff"
3-
version = "0.5.6"
3+
version = "0.5.7"
44
edition = "2021"
55
license = "Apache-2.0 OR MIT"
66
repository = "https://github.com/knickish/structdiff"
@@ -11,13 +11,14 @@ categories = ["compression"]
1111
[dependencies]
1212
nanoserde = { version = "^0.1.32", optional = true }
1313
serde = { version = "^1.0.0", optional = true, features = ["derive"] }
14-
structdiff-derive = { path = "derive", version = "=0.5.6" }
14+
structdiff-derive = { path = "derive", version = "=0.5.7" }
1515

1616
[features]
1717
"default" = []
1818
"nanoserde" = ["dep:nanoserde", "structdiff-derive/nanoserde"]
1919
"serde" = ["dep:serde", "structdiff-derive/serde"]
2020
"debug_diffs" = ["structdiff-derive/debug_diffs"]
21+
"generated_setters" = ["structdiff-derive/generated_setters"]
2122

2223
[dev-dependencies]
2324
bincode = "1.3.3"

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,23 @@ assert_ne!(diffed, second);
4848
For more examples take a look at [integration tests](/tests)
4949

5050
## Derive macro attributes
51-
- `#[difference(skip)]` - Do not consider this field when creating a diff
52-
- `#[difference(recurse)]` - Generate a StructDiff for this field when creating a diff
51+
- `#[difference(skip)]` - Do not consider this field when creating a diff
52+
- `#[difference(recurse)]` - Generate a StructDiff for this field when creating a diff
5353
- `#[difference(collection_strategy = {})]`
5454
- `"unordered_array_like"` - Generates a changeset for array-like collections of items which implement `Hash + Eq`, rather than cloning the entire list. (currently works for `Vec`, `BTreeSet`, `LinkedList`, and `HashSet`)
5555
- `"unordered_map_like"` - Generates a changeset for map-like collections for which the key implements `Hash + Eq`, rather than cloning the entire map. (currently works for `HashMap` and `BTreeMap`)
5656
- `#[difference(map_equality = {})]` - Used with `unordered_map_like`, specifies whether the equality check should consider keys only, or both keys and values
5757
- `"key_only"` - only replace a key-value pair for which the key has changed
5858
- `"key_and_value"` - replace a key-value pair if either the key or value has changed
59+
- `#[difference(setters)]` - Generate setters for all fields in the struct (used on struct)
60+
- Example: for the `field1` of the `Example` struct used above, a function with the signature `set_field1_with_diff(&mut self, value: Option<usize>) -> Option<<Self as StructDiff>::Diff>` will be generated. Useful when a single field will be changed in a struct with many fields, as it saves the comparison of all other fields.
61+
- `#[difference(setter)]` - Generate setters for this struct field (used on field)
62+
- `#[difference(setter_name = {})]` - Use this name instead of the default value when generating a setter for this field (used on field)
5963

6064
## Optional features
6165
- [`nanoserde`, `serde`] - Serialization of `Difference` derived associated types. Allows diffs to easily be sent over network.
6266
- `debug_diffs` - Derive `Debug` on the generated diff type
67+
- `generated_setters` - Enable generation of setters for struct fields. These setters automatically return a diff if a field's value is changed by the assignment.
6368

6469
### Development status
6570
This is being used actively for my own projects, although it's mostly working now. PRs will be accepted for either more tests or functionality.

derive/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "structdiff-derive"
3-
version = "0.5.6"
3+
version = "0.5.7"
44
authors = ["Makepad <[email protected]>", "Fedor <[email protected]>", "Kirk <[email protected]"]
55
edition = "2018"
66
description = "Fork of nanoserde's parsing library"
@@ -18,3 +18,4 @@ serde = { version = "^1.0.0", optional = true, features = ["derive
1818
"nanoserde" = ["dep:nanoserde"]
1919
"serde" = ["dep:serde"]
2020
"debug_diffs" = []
21+
"generated_setters" = []

derive/src/difference.rs

Lines changed: 251 additions & 9 deletions
Large diffs are not rendered by default.

derive/src/shared.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,36 @@ pub enum CollectionStrategy {
2121
UnorderedMapLikeHash(MapStrategy),
2222
}
2323

24+
#[cfg(feature = "generated_setters")]
25+
pub fn attrs_setter(attributes: &[crate::parse::Attribute]) -> (bool, bool, Option<String>) {
26+
let skip = attributes
27+
.iter()
28+
.any(|attr| attr.tokens.len() == 1 && attr.tokens[0] == "skip_setter");
29+
let local = attributes
30+
.iter()
31+
.any(|attr| attr.tokens.len() == 1 && attr.tokens[0] == "setter");
32+
33+
let Some(name_override) = attributes.iter().find_map(|attr| {
34+
if attr.tokens.len() == 2 && attr.tokens[0] == "setter_name" {
35+
36+
Some(attr.tokens[1].clone())
37+
} else {
38+
None
39+
}
40+
}) else {
41+
return (local, skip, None);
42+
};
43+
44+
(local, skip, Some(name_override))
45+
}
46+
47+
#[cfg(feature = "generated_setters")]
48+
pub fn attrs_all_setters(attributes: &[crate::parse::Attribute]) -> bool {
49+
attributes
50+
.iter()
51+
.any(|attr| attr.tokens.len() == 1 && attr.tokens[0] == "setters")
52+
}
53+
2454
pub fn attrs_recurse(attributes: &[crate::parse::Attribute]) -> bool {
2555
attributes
2656
.iter()

src/collections/unordered_array_like.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ mod test {
429429
#[test]
430430
fn test_collection_strategies() {
431431
#[derive(Debug, PartialEq, Clone, Difference, Default)]
432+
#[difference(setters)]
432433
struct TestCollection {
433434
#[difference(collection_strategy = "unordered_array_like")]
434435
test1: Vec<i32>,

src/collections/unordered_map_like.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ mod test {
508508
#[test]
509509
fn test_key_only() {
510510
#[derive(Debug, PartialEq, Clone, Difference, Default)]
511+
#[difference(setters)]
511512
struct TestCollection {
512513
#[difference(collection_strategy = "unordered_map_like")]
513514
test1: HashMap<i32, i32>,
@@ -572,6 +573,7 @@ mod test {
572573
#[test]
573574
fn test_key_value() {
574575
#[derive(Debug, PartialEq, Clone, Difference, Default)]
576+
#[difference(setters)]
575577
struct TestCollection {
576578
#[difference(
577579
collection_strategy = "unordered_map_like",

src/collections/unordered_map_like_recursive.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,12 +436,14 @@ mod test {
436436
#[cfg_attr(feature = "nanoserde", derive(DeBin, SerBin))]
437437
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
438438
#[derive(Debug, PartialEq, Clone, Difference, Default)]
439+
#[difference(setters)]
439440
pub struct TestRecurse {
440441
recurse1: i32,
441442
recurse2: Option<String>,
442443
}
443444

444445
#[derive(Debug, PartialEq, Clone, Difference, Default)]
446+
#[difference(setters)]
445447
struct TestCollection {
446448
#[difference(
447449
collection_strategy = "unordered_map_like",

tests/derives.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use structdiff::{Difference, StructDiff};
1212
#[allow(dead_code)]
1313
#[cfg(not(any(feature = "serde", feature = "nanoserde")))]
1414
#[derive(Difference)]
15+
// #[difference(setters)]
1516
pub struct TestDeriveAll<
1617
'a,
1718
'b: 'a,

tests/enums.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use structdiff::{Difference, StructDiff};
1111
#[cfg(not(feature = "nanoserde"))]
1212
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1313
#[derive(Debug, PartialEq, Clone, Difference, Default)]
14+
#[difference(setters)]
1415
pub struct Test {
1516
pub test1: i32,
1617
pub test2: String,
@@ -21,6 +22,7 @@ pub struct Test {
2122

2223
#[cfg(not(feature = "nanoserde"))]
2324
#[derive(Debug, PartialEq, Clone, Difference)]
25+
#[difference(setters)]
2426
pub struct TestSkip<A>
2527
where
2628
A: PartialEq,

0 commit comments

Comments
 (0)