use diffo::{apply, diff};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
struct User {
name: String,
email: String,
age: u32,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
struct Config {
version: String,
settings: Settings,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
struct Settings {
timeout: u32,
retries: u32,
}
fn main() {
println!("=== Diff Application Demo ===\n");
println!("1. Simple Field Update");
let user_v1 = User {
name: "Alice".into(),
email: "alice@example.com".into(),
age: 30,
};
let user_v2 = User {
name: "Alice".into(),
email: "alice@example.com".into(),
age: 31,
};
let diff_1_2 = diff(&user_v1, &user_v2).unwrap();
println!(" Changes: {}", diff_1_2.len());
let result: User = apply(&user_v1, &diff_1_2).unwrap();
println!(" Applied diff: age {} -> {}", user_v1.age, result.age);
assert_eq!(result, user_v2);
println!(" ✓ Result matches expected\n");
println!("2. Multiple Field Changes");
let user_v3 = User {
name: "Alicia".into(),
email: "alicia@newdomain.com".into(),
age: 31,
};
let diff_2_3 = diff(&user_v2, &user_v3).unwrap();
println!(" Changes: {}", diff_2_3.len());
let result: User = apply(&user_v2, &diff_2_3).unwrap();
println!(" Applied diff:");
println!(" name: {} -> {}", user_v2.name, result.name);
println!(" email: {} -> {}", user_v2.email, result.email);
assert_eq!(result, user_v3);
println!(" ✓ Result matches expected\n");
println!("3. Nested Structure Changes");
let config_v1 = Config {
version: "1.0".into(),
settings: Settings {
timeout: 30,
retries: 3,
},
};
let config_v2 = Config {
version: "1.1".into(),
settings: Settings {
timeout: 60,
retries: 5,
},
};
let diff_config = diff(&config_v1, &config_v2).unwrap();
println!(" Changes: {}", diff_config.len());
let result: Config = apply(&config_v1, &diff_config).unwrap();
println!(" Applied diff:");
println!(" version: {} -> {}", config_v1.version, result.version);
println!(
" settings.timeout: {} -> {}",
config_v1.settings.timeout, result.settings.timeout
);
println!(
" settings.retries: {} -> {}",
config_v1.settings.retries, result.settings.retries
);
assert_eq!(result, config_v2);
println!(" ✓ Result matches expected\n");
println!("4. Array Modifications");
let numbers_v1 = vec![1, 2, 3];
let numbers_v2 = vec![1, 2, 3, 4, 5];
let diff_numbers = diff(&numbers_v1, &numbers_v2).unwrap();
println!(" Changes: {}", diff_numbers.len());
let result: Vec<i32> = apply(&numbers_v1, &diff_numbers).unwrap();
println!(" Applied diff: {:?} -> {:?}", numbers_v1, result);
assert_eq!(result, numbers_v2);
println!(" ✓ Result matches expected\n");
println!("5. Roundtrip: apply(base, diff(base, target)) = target");
let original = User {
name: "Bob".into(),
email: "bob@example.com".into(),
age: 25,
};
let modified = User {
name: "Robert".into(),
email: "robert@newdomain.com".into(),
age: 26,
};
let d = diff(&original, &modified).unwrap();
let reconstructed: User = apply(&original, &d).unwrap();
println!(" Original: {:?}", original);
println!(" Modified: {:?}", modified);
println!(" Reconstructed: {:?}", reconstructed);
assert_eq!(reconstructed, modified);
println!(" ✓ Roundtrip successful!\n");
println!("6. Undo Operation (reverse diff)");
let current = User {
name: "Charlie".into(),
email: "charlie@example.com".into(),
age: 35,
};
let updated = User {
name: "Charles".into(),
email: "charles@example.com".into(),
age: 36,
};
let forward_diff = diff(¤t, &updated).unwrap();
let after_update: User = apply(¤t, &forward_diff).unwrap();
println!(" After update: {:?}", after_update);
assert_eq!(after_update, updated);
let reverse_diff = diff(&updated, ¤t).unwrap();
let after_undo: User = apply(&after_update, &reverse_diff).unwrap();
println!(" After undo: {:?}", after_undo);
assert_eq!(after_undo, current);
println!(" ✓ Undo successful!\n");
println!("=== Summary ===");
println!("Diff application enables:");
println!(" - State reconstruction from base + diff");
println!(" - Undo/redo operations");
println!(" - Version control for data structures");
println!(" - Incremental updates without full replacement");
}