1pub mod basic;
7pub mod list;
8pub mod tree;
9pub mod graph;
10pub mod builder;
11pub mod advanced;
12
13pub use basic::{LwwRegister, LwwMap, GCounter, ReplicaId, Mergeable, CRDT};
15
16pub use list::{
17 ElementId, ElementMetadata, ListElement, ListStrategy, ListConfig,
18 AddWinsList, RemoveWinsList, LwwList,
19};
20
21pub use tree::{
22 NodeId, NodeMetadata, TreeNode, TreeStrategy, TreeConfig,
23 AddWinsTree, RemoveWinsTree,
24};
25
26pub use graph::{
27 VertexId, EdgeId, VertexMetadata, EdgeMetadata, Vertex, Edge,
28 GraphStrategy, GraphConfig, AddWinsGraph, RemoveWinsGraph,
29};
30
31pub use builder::{
33 CrdtBuilder, CrdtBuilderConfig, FieldConfig, CrdtStrategy,
34 CustomCrdt, GenericCrdtField, CrdtField, BuilderError
35};
36
37pub use advanced::{
39 Rga, RgaElement, Lseq, LseqElement, YjsTree, YjsNode, YjsTreeNode,
40 Dag, DagNode, PositionId, AdvancedCrdtError
41};
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46 use crate::crdt::ReplicaId;
47 use uuid::Uuid;
48
49 fn create_replica(id: u64) -> ReplicaId {
50 ReplicaId::from(Uuid::from_u64_pair(0, id))
51 }
52
53 #[test]
54 fn test_list_crdt_integration() {
55 let replica = create_replica(1);
56 let mut list = AddWinsList::new(replica);
57
58 let id1 = list.add("item1", 1000);
59 let id2 = list.add("item2", 2000);
60
61 assert_eq!(list.len(), 2);
62 assert!(list.contains(&id1));
63 assert!(list.contains(&id2));
64 }
65
66 #[test]
67 fn test_tree_crdt_integration() {
68 let replica = create_replica(1);
69 let mut tree = AddWinsTree::new(replica);
70
71 let root_id = tree.add_root("root", 1000);
72 let child_id = tree.add_child(&root_id, "child", 2000).unwrap();
73
74 assert_eq!(tree.len(), 2);
75 assert!(tree.contains(&root_id));
76 assert!(tree.contains(&child_id));
77 }
78
79 #[test]
80 fn test_graph_crdt_integration() {
81 let replica = create_replica(1);
82 let mut graph = AddWinsGraph::new(replica);
83
84 let v1_id = graph.add_vertex("vertex1", 1000);
85 let v2_id = graph.add_vertex("vertex2", 2000);
86 let edge_id = graph.add_edge(&v1_id, &v2_id, 3000, None).unwrap();
87
88 assert_eq!(graph.vertex_count(), 2);
89 assert_eq!(graph.edge_count(), 1);
90 assert!(graph.contains_vertex(&v1_id));
91 assert!(graph.contains_edge(&edge_id));
92 }
93
94 #[test]
95 fn test_crdt_traits() {
96 let replica = create_replica(1);
97
98 let list: AddWinsList<String> = AddWinsList::new(replica);
100 let tree: AddWinsTree<String> = AddWinsTree::new(replica);
101 let graph: AddWinsGraph<String> = AddWinsGraph::new(replica);
102
103 let _: &dyn CRDT = &list;
105 let _: &dyn CRDT = &tree;
106 let _: &dyn CRDT = &graph;
107 }
108
109 #[test]
110 fn test_custom_crdt_builder_integration() {
111 let replica = create_replica(1);
112
113 let config = CrdtBuilder::new("UserProfile".to_string())
115 .add_field("name".to_string(), CrdtStrategy::Lww)
116 .add_field("age".to_string(), CrdtStrategy::Lww)
117 .add_field("friends".to_string(), CrdtStrategy::AddWins)
118 .add_optional_field("bio".to_string(), CrdtStrategy::Lww,
119 serde_json::Value::String("No bio yet".to_string()))
120 .build();
121
122 let mut profile = CustomCrdt::new(config, replica);
123
124 profile.set_field("name", serde_json::Value::String("Alice".to_string())).unwrap();
126 profile.set_field("age", serde_json::Value::Number(serde_json::Number::from(25))).unwrap();
127 profile.set_field("friends", serde_json::Value::Array(vec![
128 serde_json::Value::String("Bob".to_string()),
129 serde_json::Value::String("Charlie".to_string()),
130 ])).unwrap();
131
132 assert_eq!(profile.get_field("name"), Some(&serde_json::Value::String("Alice".to_string())));
134 assert_eq!(profile.get_field("age"), Some(&serde_json::Value::Number(serde_json::Number::from(25))));
135 assert_eq!(profile.get_field("bio"), Some(&serde_json::Value::String("No bio yet".to_string())));
136
137 let _: &dyn CRDT = &profile;
139
140 let mut profile2 = profile.clone();
142
143 std::thread::sleep(std::time::Duration::from_millis(1));
145
146 profile2.set_field("name", serde_json::Value::String("Alice Updated".to_string())).unwrap();
147 profile2.set_field("friends", serde_json::Value::Array(vec![
148 serde_json::Value::String("David".to_string()),
149 ])).unwrap();
150
151 profile.merge(&profile2).unwrap();
153
154 assert_eq!(profile.get_field("name"), Some(&serde_json::Value::String("Alice Updated".to_string())));
156 if let Some(friends) = profile.get_field("friends") {
158 if let Some(friends_array) = friends.as_array() {
159 assert_eq!(friends_array.len(), 3); }
161 }
162 }
163
164 #[test]
165 fn test_advanced_crdt_integration() {
166 let replica1 = create_replica(1);
167 let replica2 = create_replica(2);
168
169 let mut rga1 = Rga::new(replica1.clone());
171 let mut rga2 = Rga::new(replica2.clone());
172
173 let _pos1 = rga1.insert_after("hello".to_string(), None).unwrap();
174 let _pos2 = rga2.insert_after("world".to_string(), None).unwrap();
175
176 rga1.merge(&rga2).unwrap();
177 let elements = rga1.to_vec();
178 assert!(elements.contains(&"hello".to_string()));
179 assert!(elements.contains(&"world".to_string()));
180
181 let mut lseq1 = Lseq::new(replica1.clone());
183 let mut lseq2 = Lseq::new(replica2.clone());
184
185 lseq1.insert("item1".to_string(), None).unwrap();
186 lseq2.insert("item2".to_string(), None).unwrap();
187
188 lseq1.merge(&lseq2).unwrap();
189 let elements = lseq1.to_vec();
190 assert!(elements.contains(&"item1".to_string()));
191 assert!(elements.contains(&"item2".to_string()));
192
193 let mut tree1 = YjsTree::new(replica1.clone());
195 let mut tree2 = YjsTree::new(replica2.clone());
196
197 let root1_id = tree1.add_root("root1".to_string()).unwrap();
198 let root2_id = tree2.add_root("root2".to_string()).unwrap();
199
200 tree1.add_child(&root1_id, "child1".to_string()).unwrap();
201 tree2.add_child(&root2_id, "child2".to_string()).unwrap();
202
203 tree1.merge(&tree2).unwrap();
204 assert_eq!(tree1.len(), 4); let mut dag1 = Dag::new(replica1);
208 let mut dag2 = Dag::new(replica2);
209
210 let node1_id = dag1.add_node("node1".to_string()).unwrap();
211 let node2_id = dag2.add_node("node2".to_string()).unwrap();
212
213 dag1.merge(&dag2).unwrap();
216 assert_eq!(dag1.len(), 2);
217 }
218}