use crdt_lite::{DefaultMergeRule, CRDT};
fn main() {
println!("=== CRDT Rust Port - Basic Usage Example ===\n");
let mut node1: CRDT<String, String, String> = CRDT::new(1, None);
let mut node2: CRDT<String, String, String> = CRDT::new(2, None);
println!("Created two CRDT nodes with IDs 1 and 2\n");
println!("Node 1: Inserting user 'alice'...");
let changes1 = node1.insert_or_update(
&"alice".to_string(),
vec![
("name".to_string(), "Alice".to_string()),
("email".to_string(), "alice@example.com".to_string()),
("role".to_string(), "admin".to_string()),
],
);
println!(" Created {} changes", changes1.len());
println!("\nNode 2: Inserting user 'alice' with different data...");
let changes2 = node2.insert_or_update(
&"alice".to_string(),
vec![
("name".to_string(), "Alice Smith".to_string()),
("email".to_string(), "alice.smith@example.com".to_string()),
("role".to_string(), "user".to_string()),
],
);
println!(" Created {} changes", changes2.len());
println!("\n--- Merging changes ---");
let merge_rule = DefaultMergeRule;
println!("Node 1: Receiving changes from Node 2...");
node1.merge_changes(changes2, &merge_rule);
println!("Node 2: Receiving changes from Node 1...");
node2.merge_changes(changes1, &merge_rule);
println!("\n--- Results ---");
if node1.get_data() == node2.get_data() {
println!("✓ Both nodes have converged to the same state!");
} else {
println!("✗ Nodes have different states (unexpected)");
}
if let Some(record) = node1.get_record(&"alice".to_string()) {
println!("\nFinal record for 'alice':");
for (field, value) in &record.fields {
println!(" {}: {}", field, value);
}
println!("\nNote: Node 2 won the conflict due to higher node_id (last-write-wins)");
}
println!("\n--- Updating a field ---");
println!("Node 1: Updating alice's role to 'superadmin'...");
let update_changes = node1.insert_or_update(
&"alice".to_string(),
vec![("role".to_string(), "superadmin".to_string())],
);
println!("Node 2: Merging update...");
node2.merge_changes(update_changes, &merge_rule);
if let Some(record) = node2.get_record(&"alice".to_string()) {
println!("Updated role: {}", record.fields.get("role").unwrap());
}
println!("\n--- Deleting a record ---");
println!("Node 1: Deleting user 'alice'...");
if let Some(delete_change) = node1.delete_record(&"alice".to_string()) {
println!(" Created tombstone");
println!("Node 2: Merging deletion...");
node2.merge_changes(vec![delete_change], &merge_rule);
}
println!(
"\nIs 'alice' tombstoned on Node 1? {}",
node1.is_tombstoned(&"alice".to_string())
);
println!(
"Is 'alice' tombstoned on Node 2? {}",
node2.is_tombstoned(&"alice".to_string())
);
println!("\n--- Attempting to re-insert tombstoned record ---");
let reinsert_attempt = node1.insert_or_update(
&"alice".to_string(),
vec![("name".to_string(), "Alice Reborn".to_string())],
);
println!(
"Changes created: {} (tombstone prevents insertion)",
reinsert_attempt.len()
);
println!("\n--- Change Tracking ---");
let mut node3: CRDT<String, String, String> = CRDT::new(3, None);
let _ = node3.insert_or_update(
&"bob".to_string(),
vec![("name".to_string(), "Bob".to_string())],
);
let version_1 = node3.get_clock().current_time();
let _ = node3.insert_or_update(
&"bob".to_string(),
vec![("email".to_string(), "bob@example.com".to_string())],
);
let _ = node3.insert_or_update(
&"charlie".to_string(),
vec![("name".to_string(), "Charlie".to_string())],
);
let changes_since_v1 = node3.get_changes_since(version_1);
println!(
"Changes since version {}: {}",
version_1,
changes_since_v1.len()
);
for change in &changes_since_v1 {
println!(
" - {:?}: {:?} = {:?}",
change.record_id, change.col_name, change.value
);
}
println!("\n=== Example Complete ===");
}