Skip to main content

serde_patch/
lib.rs

1mod apply_patch;
2mod apply_patch_mut;
3mod diff_patch;
4
5pub use apply_patch::apply;
6pub use apply_patch_mut::apply_mut;
7pub use diff_patch::diff;
8pub use diff_patch::diff_including;
9
10#[cfg(test)]
11mod tests {
12    use serde::{Deserialize, Serialize};
13    use serde_json::json;
14
15    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
16    struct Profile {
17        bio: String,
18        avatar_url: Option<String>,
19    }
20
21    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
22    struct User {
23        id: u32,
24        username: String,
25        age: u8,
26        active: bool,
27        profile: Option<Profile>,
28    }
29
30    #[test]
31    fn test_diff() {
32        let old = User {
33            id: 1001,
34            username: "alice".to_string(),
35            age: 30,
36            active: true,
37            profile: Some(Profile {
38                bio: "Software engineer".to_string(),
39                avatar_url: Some("https://example.com/alice-old.jpg".to_string()),
40            }),
41        };
42
43        let new = User {
44            id: 1001,
45            username: "alice".to_string(),
46            age: 31,
47            active: false,
48            profile: Some(Profile {
49                bio: "Senior software engineer".to_string(),
50                avatar_url: None,
51            }),
52        };
53
54        let patch = serde_json::to_string(&crate::diff(&old, &new).unwrap()).unwrap();
55
56        assert_eq!(
57            patch,
58            r#"{"active":false,"age":31,"profile":{"avatar_url":null,"bio":"Senior software engineer"}}"#
59        );
60    }
61
62    #[test]
63    fn test_diff_forced_nested() {
64        let old = User {
65            id: 1001,
66            username: "alice".to_string(),
67            age: 30,
68            active: true,
69            profile: Some(Profile {
70                bio: "Software engineer".to_string(), // igual em new
71                avatar_url: Some("https://example.com/alice-old.jpg".to_string()),
72            }),
73        };
74        let new = User {
75            id: 1001,
76            username: "alice".to_string(),
77            age: 31,
78            active: false,
79            profile: Some(Profile {
80                bio: "Software engineer".to_string(),
81                avatar_url: None,
82            }),
83        };
84
85        let patch_value = crate::diff_including(&old, &new, &["profile.bio"]).unwrap();
86
87        let expected = json!({
88            "age": 31,
89            "active": false,
90            "profile": {
91                "bio": "Software engineer",
92                "avatar_url": null
93            }
94        });
95
96        assert_eq!(patch_value, expected);
97    }
98
99    #[test]
100    fn test_apply_patch_immutable() {
101        let current = User {
102            id: 1001,
103            username: "alice".to_string(),
104            age: 30,
105            active: true,
106            profile: Some(Profile {
107                bio: "Software engineer".to_string(),
108                avatar_url: Some("https://example.com/alice-old.jpg".to_string()),
109            }),
110        };
111
112        let patch = r#"
113            {
114                "age": 31,
115                "active": false,
116                "profile": {
117                    "bio": "Senior software engineer",
118                    "avatar_url": null
119                }
120            }
121        "#;
122
123        let updated: User = crate::apply(current, patch).unwrap();
124
125        assert_eq!(
126            updated,
127            User {
128                id: 1001,
129                username: "alice".to_string(),
130                age: 31,
131                active: false,
132                profile: Some(Profile {
133                    bio: "Senior software engineer".to_string(),
134                    avatar_url: None,
135                }),
136            }
137        );
138    }
139
140    #[test]
141    fn test_apply_patch_mutable() {
142        let mut current = User {
143            id: 1001,
144            username: "alice".to_string(),
145            age: 30,
146            active: true,
147            profile: Some(Profile {
148                bio: "Software engineer".to_string(),
149                avatar_url: Some("https://example.com/alice-old.jpg".to_string()),
150            }),
151        };
152
153        let patch = r#"
154            {
155                "age": 31,
156                "active": false,
157                "profile": {
158                    "bio": "Senior software engineer",
159                    "avatar_url": null
160                }
161            }
162        "#;
163
164        crate::apply_mut(&mut current, patch).unwrap();
165
166        assert_eq!(
167            current,
168            User {
169                id: 1001,
170                username: "alice".to_string(),
171                age: 31,
172                active: false,
173                profile: Some(Profile {
174                    bio: "Senior software engineer".to_string(),
175                    avatar_url: None,
176                }),
177            }
178        );
179    }
180}