oxihuman_core/
version_vector.rs1#![allow(dead_code)]
7
8use std::collections::HashMap;
9
10#[allow(dead_code)]
12#[derive(Debug, Clone, PartialEq)]
13pub struct VersionVector {
14 pub clocks: HashMap<String, u64>,
15}
16
17#[allow(dead_code)]
19pub fn new_version_vector() -> VersionVector {
20 VersionVector {
21 clocks: HashMap::new(),
22 }
23}
24
25#[allow(dead_code)]
27pub fn vv_increment(vv: &mut VersionVector, node: &str) {
28 let entry = vv.clocks.entry(node.to_string()).or_insert(0);
29 *entry += 1;
30}
31
32#[allow(dead_code)]
34pub fn vv_get(vv: &VersionVector, node: &str) -> u64 {
35 *vv.clocks.get(node).unwrap_or(&0)
36}
37
38#[allow(dead_code)]
40pub fn vv_merge(a: &VersionVector, b: &VersionVector) -> VersionVector {
41 let mut result = a.clone();
42 for (node, &val) in &b.clocks {
43 let entry = result.clocks.entry(node.clone()).or_insert(0);
44 if val > *entry {
45 *entry = val;
46 }
47 }
48 result
49}
50
51#[allow(dead_code)]
53pub fn vv_happens_before(a: &VersionVector, b: &VersionVector) -> bool {
54 let all_le = a.clocks.iter().all(|(k, &v)| vv_get(b, k) >= v);
56 let any_lt = a.clocks.iter().any(|(k, &v)| vv_get(b, k) > v)
58 || b.clocks.keys().any(|k| !a.clocks.contains_key(k.as_str()));
59 all_le && any_lt
60}
61
62#[allow(dead_code)]
64pub fn vv_concurrent(a: &VersionVector, b: &VersionVector) -> bool {
65 !vv_happens_before(a, b) && !vv_happens_before(b, a) && a != b
66}
67
68#[allow(dead_code)]
70pub fn vv_compare(a: &VersionVector, b: &VersionVector) -> i32 {
71 if a == b {
72 0
73 } else if vv_happens_before(a, b) {
74 -1
75 } else if vv_happens_before(b, a) {
76 1
77 } else {
78 2
79 }
80}
81
82#[allow(dead_code)]
84pub fn vv_node_count(vv: &VersionVector) -> usize {
85 vv.clocks.len()
86}
87
88#[allow(dead_code)]
90pub fn vv_reset_node(vv: &mut VersionVector, node: &str) {
91 vv.clocks.insert(node.to_string(), 0);
92}
93
94#[allow(dead_code)]
96pub fn vv_nodes(vv: &VersionVector) -> Vec<&str> {
97 vv.clocks.keys().map(|s| s.as_str()).collect()
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn new_is_empty() {
106 let vv = new_version_vector();
107 assert_eq!(vv_node_count(&vv), 0);
108 }
109
110 #[test]
111 fn increment_and_get() {
112 let mut vv = new_version_vector();
113 vv_increment(&mut vv, "A");
114 vv_increment(&mut vv, "A");
115 assert_eq!(vv_get(&vv, "A"), 2);
116 }
117
118 #[test]
119 fn get_missing_returns_zero() {
120 let vv = new_version_vector();
121 assert_eq!(vv_get(&vv, "X"), 0);
122 }
123
124 #[test]
125 fn merge_takes_max() {
126 let mut a = new_version_vector();
127 let mut b = new_version_vector();
128 vv_increment(&mut a, "A");
129 vv_increment(&mut b, "A");
130 vv_increment(&mut b, "A");
131 vv_increment(&mut b, "B");
132 let merged = vv_merge(&a, &b);
133 assert_eq!(vv_get(&merged, "A"), 2);
134 assert_eq!(vv_get(&merged, "B"), 1);
135 }
136
137 #[test]
138 fn happens_before_basic() {
139 let mut a = new_version_vector();
140 let mut b = new_version_vector();
141 vv_increment(&mut a, "A");
142 vv_increment(&mut b, "A");
143 vv_increment(&mut b, "A");
144 assert!(vv_happens_before(&a, &b));
145 assert!(!vv_happens_before(&b, &a));
146 }
147
148 #[test]
149 fn equal_vectors_not_happens_before() {
150 let mut a = new_version_vector();
151 let mut b = new_version_vector();
152 vv_increment(&mut a, "A");
153 vv_increment(&mut b, "A");
154 assert!(!vv_happens_before(&a, &b));
155 }
156
157 #[test]
158 fn concurrent_vectors() {
159 let mut a = new_version_vector();
160 let mut b = new_version_vector();
161 vv_increment(&mut a, "A");
162 vv_increment(&mut b, "B");
163 assert!(vv_concurrent(&a, &b));
164 }
165
166 #[test]
167 fn compare_equal() {
168 let mut a = new_version_vector();
169 let mut b = new_version_vector();
170 vv_increment(&mut a, "X");
171 vv_increment(&mut b, "X");
172 assert_eq!(vv_compare(&a, &b), 0);
173 }
174
175 #[test]
176 fn reset_node() {
177 let mut vv = new_version_vector();
178 vv_increment(&mut vv, "N");
179 vv_increment(&mut vv, "N");
180 vv_reset_node(&mut vv, "N");
181 assert_eq!(vv_get(&vv, "N"), 0);
182 }
183
184 #[test]
185 fn node_count_grows() {
186 let mut vv = new_version_vector();
187 vv_increment(&mut vv, "A");
188 vv_increment(&mut vv, "B");
189 assert_eq!(vv_node_count(&vv), 2);
190 }
191}