pub mod basic;
pub mod list;
pub mod tree;
pub mod graph;
pub mod builder;
pub mod advanced;
pub use basic::{LwwRegister, LwwMap, GCounter, ReplicaId, Mergeable, CRDT};
pub use list::{
ElementId, ElementMetadata, ListElement, ListStrategy, ListConfig,
AddWinsList, RemoveWinsList, LwwList,
};
pub use tree::{
NodeId, NodeMetadata, TreeNode, TreeStrategy, TreeConfig,
AddWinsTree, RemoveWinsTree,
};
pub use graph::{
VertexId, EdgeId, VertexMetadata, EdgeMetadata, Vertex, Edge,
GraphStrategy, GraphConfig, AddWinsGraph, RemoveWinsGraph,
};
pub use builder::{
CrdtBuilder, CrdtBuilderConfig, FieldConfig, CrdtStrategy,
CustomCrdt, GenericCrdtField, CrdtField, BuilderError
};
pub use advanced::{
Rga, RgaElement, Lseq, LseqElement, YjsTree, YjsNode, YjsTreeNode,
Dag, DagNode, PositionId, AdvancedCrdtError
};
#[cfg(test)]
mod tests {
use super::*;
use crate::crdt::ReplicaId;
use uuid::Uuid;
fn create_replica(id: u64) -> ReplicaId {
ReplicaId::from(Uuid::from_u64_pair(0, id))
}
#[test]
fn test_list_crdt_integration() {
let replica = create_replica(1);
let mut list = AddWinsList::new(replica);
let id1 = list.add("item1", 1000);
let id2 = list.add("item2", 2000);
assert_eq!(list.len(), 2);
assert!(list.contains(&id1));
assert!(list.contains(&id2));
}
#[test]
fn test_tree_crdt_integration() {
let replica = create_replica(1);
let mut tree = AddWinsTree::new(replica);
let root_id = tree.add_root("root", 1000);
let child_id = tree.add_child(&root_id, "child", 2000).unwrap();
assert_eq!(tree.len(), 2);
assert!(tree.contains(&root_id));
assert!(tree.contains(&child_id));
}
#[test]
fn test_graph_crdt_integration() {
let replica = create_replica(1);
let mut graph = AddWinsGraph::new(replica);
let v1_id = graph.add_vertex("vertex1", 1000);
let v2_id = graph.add_vertex("vertex2", 2000);
let edge_id = graph.add_edge(&v1_id, &v2_id, 3000, None).unwrap();
assert_eq!(graph.vertex_count(), 2);
assert_eq!(graph.edge_count(), 1);
assert!(graph.contains_vertex(&v1_id));
assert!(graph.contains_edge(&edge_id));
}
#[test]
fn test_crdt_traits() {
let replica = create_replica(1);
let list: AddWinsList<String> = AddWinsList::new(replica);
let tree: AddWinsTree<String> = AddWinsTree::new(replica);
let graph: AddWinsGraph<String> = AddWinsGraph::new(replica);
let _: &dyn CRDT = &list;
let _: &dyn CRDT = &tree;
let _: &dyn CRDT = &graph;
}
#[test]
fn test_custom_crdt_builder_integration() {
let replica = create_replica(1);
let config = CrdtBuilder::new("UserProfile".to_string())
.add_field("name".to_string(), CrdtStrategy::Lww)
.add_field("age".to_string(), CrdtStrategy::Lww)
.add_field("friends".to_string(), CrdtStrategy::AddWins)
.add_optional_field("bio".to_string(), CrdtStrategy::Lww,
serde_json::Value::String("No bio yet".to_string()))
.build();
let mut profile = CustomCrdt::new(config, replica);
profile.set_field("name", serde_json::Value::String("Alice".to_string())).unwrap();
profile.set_field("age", serde_json::Value::Number(serde_json::Number::from(25))).unwrap();
profile.set_field("friends", serde_json::Value::Array(vec![
serde_json::Value::String("Bob".to_string()),
serde_json::Value::String("Charlie".to_string()),
])).unwrap();
assert_eq!(profile.get_field("name"), Some(&serde_json::Value::String("Alice".to_string())));
assert_eq!(profile.get_field("age"), Some(&serde_json::Value::Number(serde_json::Number::from(25))));
assert_eq!(profile.get_field("bio"), Some(&serde_json::Value::String("No bio yet".to_string())));
let _: &dyn CRDT = &profile;
let mut profile2 = profile.clone();
std::thread::sleep(std::time::Duration::from_millis(1));
profile2.set_field("name", serde_json::Value::String("Alice Updated".to_string())).unwrap();
profile2.set_field("friends", serde_json::Value::Array(vec![
serde_json::Value::String("David".to_string()),
])).unwrap();
profile.merge(&profile2).unwrap();
assert_eq!(profile.get_field("name"), Some(&serde_json::Value::String("Alice Updated".to_string())));
if let Some(friends) = profile.get_field("friends") {
if let Some(friends_array) = friends.as_array() {
assert_eq!(friends_array.len(), 3); }
}
}
#[test]
fn test_advanced_crdt_integration() {
let replica1 = create_replica(1);
let replica2 = create_replica(2);
let mut rga1 = Rga::new(replica1.clone());
let mut rga2 = Rga::new(replica2.clone());
let _pos1 = rga1.insert_after("hello".to_string(), None).unwrap();
let _pos2 = rga2.insert_after("world".to_string(), None).unwrap();
rga1.merge(&rga2).unwrap();
let elements = rga1.to_vec();
assert!(elements.contains(&"hello".to_string()));
assert!(elements.contains(&"world".to_string()));
let mut lseq1 = Lseq::new(replica1.clone());
let mut lseq2 = Lseq::new(replica2.clone());
lseq1.insert("item1".to_string(), None).unwrap();
lseq2.insert("item2".to_string(), None).unwrap();
lseq1.merge(&lseq2).unwrap();
let elements = lseq1.to_vec();
assert!(elements.contains(&"item1".to_string()));
assert!(elements.contains(&"item2".to_string()));
let mut tree1 = YjsTree::new(replica1.clone());
let mut tree2 = YjsTree::new(replica2.clone());
let root1_id = tree1.add_root("root1".to_string()).unwrap();
let root2_id = tree2.add_root("root2".to_string()).unwrap();
tree1.add_child(&root1_id, "child1".to_string()).unwrap();
tree2.add_child(&root2_id, "child2".to_string()).unwrap();
tree1.merge(&tree2).unwrap();
assert_eq!(tree1.len(), 4);
let mut dag1 = Dag::new(replica1);
let mut dag2 = Dag::new(replica2);
let node1_id = dag1.add_node("node1".to_string()).unwrap();
let node2_id = dag2.add_node("node2".to_string()).unwrap();
dag1.merge(&dag2).unwrap();
assert_eq!(dag1.len(), 2);
}
}