1use serde_json::Value as JsonValue;
32use std::error::Error;
33use std::fmt;
34
35pub use json_patch::{
37 AddOperation, CopyOperation, MoveOperation, Patch, PatchOperation, RemoveOperation,
38 ReplaceOperation, TestOperation,
39};
40use jsonptr::PointerBuf;
41
42#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct PatchError {
45 message: String,
46}
47
48impl PatchError {
49 pub fn new(message: impl Into<String>) -> Self {
51 Self {
52 message: message.into(),
53 }
54 }
55}
56
57impl fmt::Display for PatchError {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 write!(f, "Patch error: {}", self.message)
60 }
61}
62
63impl Error for PatchError {}
64
65impl From<json_patch::PatchError> for PatchError {
66 fn from(err: json_patch::PatchError) -> Self {
67 Self::new(format!("{}", err))
68 }
69}
70
71pub fn create_patch(from: &JsonValue, to: &JsonValue) -> Patch {
90 json_patch::diff(from, to)
91}
92
93pub fn apply_patch(target: &mut JsonValue, patch: &Patch) -> Result<(), PatchError> {
113 json_patch::patch(target, patch.0.as_slice()).map_err(PatchError::from)
114}
115
116pub fn apply_patch_from_value(target: &mut JsonValue, patch: &JsonValue) -> Result<(), PatchError> {
141 let patch: Patch = serde_json::from_value(patch.clone())
142 .map_err(|e| PatchError::new(format!("Invalid patch format: {}", e)))?;
143 apply_patch(target, &patch)
144}
145
146pub fn patch_to_value(patch: &Patch) -> JsonValue {
166 serde_json::to_value(patch).unwrap_or(JsonValue::Array(vec![]))
167}
168
169pub fn patch_to_vec(patch: &Patch) -> Vec<JsonValue> {
189 patch
190 .0
191 .iter()
192 .filter_map(|op| serde_json::to_value(op).ok())
193 .collect()
194}
195
196#[derive(Debug, Clone, Default)]
216pub struct PatchBuilder {
217 operations: Vec<PatchOperation>,
218}
219
220impl PatchBuilder {
221 pub fn new() -> Self {
223 Self::default()
224 }
225
226 pub fn add(mut self, path: impl AsRef<str>, value: JsonValue) -> Self {
231 self.operations.push(PatchOperation::Add(AddOperation {
232 path: PointerBuf::parse(path.as_ref()).unwrap_or_default(),
233 value,
234 }));
235 self
236 }
237
238 pub fn remove(mut self, path: impl AsRef<str>) -> Self {
242 self.operations
243 .push(PatchOperation::Remove(RemoveOperation {
244 path: PointerBuf::parse(path.as_ref()).unwrap_or_default(),
245 }));
246 self
247 }
248
249 pub fn replace(mut self, path: impl AsRef<str>, value: JsonValue) -> Self {
254 self.operations
255 .push(PatchOperation::Replace(ReplaceOperation {
256 path: PointerBuf::parse(path.as_ref()).unwrap_or_default(),
257 value,
258 }));
259 self
260 }
261
262 pub fn move_value(mut self, from: impl AsRef<str>, path: impl AsRef<str>) -> Self {
267 self.operations.push(PatchOperation::Move(MoveOperation {
268 from: PointerBuf::parse(from.as_ref()).unwrap_or_default(),
269 path: PointerBuf::parse(path.as_ref()).unwrap_or_default(),
270 }));
271 self
272 }
273
274 pub fn copy(mut self, from: impl AsRef<str>, path: impl AsRef<str>) -> Self {
279 self.operations.push(PatchOperation::Copy(CopyOperation {
280 from: PointerBuf::parse(from.as_ref()).unwrap_or_default(),
281 path: PointerBuf::parse(path.as_ref()).unwrap_or_default(),
282 }));
283 self
284 }
285
286 pub fn test(mut self, path: impl AsRef<str>, value: JsonValue) -> Self {
291 self.operations.push(PatchOperation::Test(TestOperation {
292 path: PointerBuf::parse(path.as_ref()).unwrap_or_default(),
293 value,
294 }));
295 self
296 }
297
298 pub fn build(self) -> Patch {
300 Patch(self.operations)
301 }
302
303 pub fn build_vec(self) -> Vec<JsonValue> {
307 patch_to_vec(&self.build())
308 }
309}
310
311pub fn can_apply_patch(target: &JsonValue, patch: &Patch) -> bool {
329 let mut test_target = target.clone();
330 apply_patch(&mut test_target, patch).is_ok()
331}
332
333pub fn merge_patches(first: &Patch, second: &Patch) -> Patch {
354 let mut operations = first.0.clone();
355 operations.extend(second.0.clone());
356 Patch(operations)
357}
358
359#[cfg(test)]
360mod tests {
361 use super::*;
362 use serde_json::json;
363
364 #[test]
365 fn test_create_patch_simple() {
366 let from = json!({"count": 0});
367 let to = json!({"count": 5});
368
369 let patch = create_patch(&from, &to);
370 assert!(!patch.0.is_empty());
371
372 let mut result = from.clone();
374 apply_patch(&mut result, &patch).unwrap();
375 assert_eq!(result, to);
376 }
377
378 #[test]
379 fn test_create_patch_add_field() {
380 let from = json!({"name": "Alice"});
381 let to = json!({"name": "Alice", "age": 30});
382
383 let patch = create_patch(&from, &to);
384
385 let mut result = from.clone();
386 apply_patch(&mut result, &patch).unwrap();
387 assert_eq!(result, to);
388 }
389
390 #[test]
391 fn test_create_patch_remove_field() {
392 let from = json!({"name": "Alice", "temp": "value"});
393 let to = json!({"name": "Alice"});
394
395 let patch = create_patch(&from, &to);
396
397 let mut result = from.clone();
398 apply_patch(&mut result, &patch).unwrap();
399 assert_eq!(result, to);
400 }
401
402 #[test]
403 fn test_create_patch_array_operations() {
404 let from = json!({"items": ["a", "b"]});
405 let to = json!({"items": ["a", "b", "c"]});
406
407 let patch = create_patch(&from, &to);
408
409 let mut result = from.clone();
410 apply_patch(&mut result, &patch).unwrap();
411 assert_eq!(result, to);
412 }
413
414 #[test]
415 fn test_apply_patch_from_value() {
416 let mut state = json!({"count": 0});
417 let patch_json = json!([
418 {"op": "replace", "path": "/count", "value": 42}
419 ]);
420
421 apply_patch_from_value(&mut state, &patch_json).unwrap();
422 assert_eq!(state["count"], 42);
423 }
424
425 #[test]
426 fn test_apply_patch_from_value_invalid() {
427 let mut state = json!({"count": 0});
428 let invalid_patch = json!("not an array");
429
430 let result = apply_patch_from_value(&mut state, &invalid_patch);
431 assert!(result.is_err());
432 }
433
434 #[test]
435 fn test_patch_to_value() {
436 let patch = create_patch(&json!({"x": 1}), &json!({"x": 2}));
437 let value = patch_to_value(&patch);
438
439 assert!(value.is_array());
440 }
441
442 #[test]
443 fn test_patch_to_vec() {
444 let patch = create_patch(&json!({"a": 1, "b": 2}), &json!({"a": 1, "b": 3, "c": 4}));
445 let ops = patch_to_vec(&patch);
446
447 assert!(!ops.is_empty());
449 for op in &ops {
450 assert!(op.is_object());
451 assert!(op.get("op").is_some());
452 }
453 }
454
455 #[test]
456 fn test_patch_builder_add() {
457 let patch = PatchBuilder::new()
458 .add("/name", json!("Alice"))
459 .build();
460
461 let mut state = json!({});
462 apply_patch(&mut state, &patch).unwrap();
463 assert_eq!(state["name"], "Alice");
464 }
465
466 #[test]
467 fn test_patch_builder_replace() {
468 let patch = PatchBuilder::new()
469 .replace("/count", json!(10))
470 .build();
471
472 let mut state = json!({"count": 0});
473 apply_patch(&mut state, &patch).unwrap();
474 assert_eq!(state["count"], 10);
475 }
476
477 #[test]
478 fn test_patch_builder_remove() {
479 let patch = PatchBuilder::new().remove("/temp").build();
480
481 let mut state = json!({"name": "Alice", "temp": "value"});
482 apply_patch(&mut state, &patch).unwrap();
483 assert!(state.get("temp").is_none());
484 assert_eq!(state["name"], "Alice");
485 }
486
487 #[test]
488 fn test_patch_builder_move() {
489 let patch = PatchBuilder::new()
490 .move_value("/old", "/new")
491 .build();
492
493 let mut state = json!({"old": "value"});
494 apply_patch(&mut state, &patch).unwrap();
495 assert!(state.get("old").is_none());
496 assert_eq!(state["new"], "value");
497 }
498
499 #[test]
500 fn test_patch_builder_copy() {
501 let patch = PatchBuilder::new()
502 .copy("/source", "/dest")
503 .build();
504
505 let mut state = json!({"source": "value"});
506 apply_patch(&mut state, &patch).unwrap();
507 assert_eq!(state["source"], "value");
508 assert_eq!(state["dest"], "value");
509 }
510
511 #[test]
512 fn test_patch_builder_test() {
513 let patch = PatchBuilder::new()
515 .test("/count", json!(0))
516 .replace("/count", json!(1))
517 .build();
518
519 let mut state = json!({"count": 0});
520 apply_patch(&mut state, &patch).unwrap();
521 assert_eq!(state["count"], 1);
522 }
523
524 #[test]
525 fn test_patch_builder_test_fails() {
526 let patch = PatchBuilder::new()
527 .test("/count", json!(999)) .replace("/count", json!(1))
529 .build();
530
531 let mut state = json!({"count": 0});
532 let result = apply_patch(&mut state, &patch);
533 assert!(result.is_err());
534 }
535
536 #[test]
537 fn test_patch_builder_build_vec() {
538 let ops = PatchBuilder::new()
539 .add("/a", json!(1))
540 .replace("/b", json!(2))
541 .build_vec();
542
543 assert_eq!(ops.len(), 2);
544 }
545
546 #[test]
547 fn test_can_apply_patch() {
548 let state = json!({"count": 0});
549
550 let valid_patch = PatchBuilder::new().replace("/count", json!(1)).build();
551 assert!(can_apply_patch(&state, &valid_patch));
552
553 let invalid_patch = PatchBuilder::new().remove("/nonexistent").build();
554 assert!(!can_apply_patch(&state, &invalid_patch));
555 }
556
557 #[test]
558 fn test_merge_patches() {
559 let patch1 = PatchBuilder::new().add("/a", json!(1)).build();
560 let patch2 = PatchBuilder::new().add("/b", json!(2)).build();
561
562 let merged = merge_patches(&patch1, &patch2);
563 assert_eq!(merged.0.len(), 2);
564
565 let mut state = json!({});
566 apply_patch(&mut state, &merged).unwrap();
567 assert_eq!(state["a"], 1);
568 assert_eq!(state["b"], 2);
569 }
570
571 #[test]
572 fn test_patch_error_display() {
573 let err = PatchError::new("test error");
574 assert!(err.to_string().contains("test error"));
575 }
576
577 #[test]
578 fn test_complex_nested_patch() {
579 let from = json!({
580 "user": {
581 "profile": {
582 "name": "Alice",
583 "settings": {
584 "theme": "light"
585 }
586 }
587 }
588 });
589
590 let to = json!({
591 "user": {
592 "profile": {
593 "name": "Alice",
594 "settings": {
595 "theme": "dark",
596 "notifications": true
597 }
598 }
599 }
600 });
601
602 let patch = create_patch(&from, &to);
603
604 let mut result = from.clone();
605 apply_patch(&mut result, &patch).unwrap();
606 assert_eq!(result, to);
607 }
608
609 #[test]
610 fn test_empty_patch() {
611 let state = json!({"count": 0});
612 let patch = create_patch(&state, &state);
613
614 assert!(patch.0.is_empty());
616
617 let mut result = state.clone();
619 apply_patch(&mut result, &patch).unwrap();
620 assert_eq!(result, state);
621 }
622}