leptos_sync_core/crdt/basic/
traits.rs1use super::replica_id::ReplicaId;
4
5pub trait Mergeable: Clone + Send + Sync {
7 type Error: std::error::Error + Send + Sync + 'static + Sized;
8
9 fn merge(&mut self, other: &Self) -> Result<(), Self::Error>;
11
12 fn has_conflict(&self, other: &Self) -> bool;
14}
15
16pub trait CRDT {
18 fn replica_id(&self) -> &ReplicaId;
19}
20
21#[cfg(test)]
22mod tests {
23 use super::*;
24
25 #[derive(Debug, Clone, PartialEq)]
27 struct TestCrdt {
28 replica_id: ReplicaId,
29 value: String,
30 }
31
32 impl TestCrdt {
33 fn new(replica_id: ReplicaId, value: String) -> Self {
34 Self { replica_id, value }
35 }
36 }
37
38 impl CRDT for TestCrdt {
39 fn replica_id(&self) -> &ReplicaId {
40 &self.replica_id
41 }
42 }
43
44 impl Mergeable for TestCrdt {
45 type Error = std::io::Error;
46
47 fn merge(&mut self, other: &Self) -> Result<(), Self::Error> {
48 if other.value.len() > self.value.len() {
50 self.value = other.value.clone();
51 }
52 Ok(())
53 }
54
55 fn has_conflict(&self, other: &Self) -> bool {
56 self.value != other.value
57 }
58 }
59
60 #[test]
61 fn test_crdt_trait() {
62 let replica_id = ReplicaId::default();
63 let crdt = TestCrdt::new(replica_id, "test".to_string());
64
65 assert_eq!(crdt.replica_id(), &replica_id);
66 }
67
68 #[test]
69 fn test_mergeable_trait() {
70 let replica_id = ReplicaId::default();
71 let mut crdt1 = TestCrdt::new(replica_id, "short".to_string());
72 let crdt2 = TestCrdt::new(replica_id, "much longer string".to_string());
73
74 crdt1.merge(&crdt2).unwrap();
76 assert_eq!(crdt1.value, "much longer string");
77
78 let crdt3 = TestCrdt::new(replica_id, "different".to_string());
80 assert!(crdt1.has_conflict(&crdt3));
81 assert!(!crdt1.has_conflict(&crdt2));
82 }
83}