sapphire_framework_sync/
vv.rs1use std::collections::BTreeMap;
4
5use serde::{Deserialize, Serialize};
6
7use crate::id::ReplicaId;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
11pub struct Dot {
12 pub replica: ReplicaId,
13 pub counter: u64,
14}
15
16#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
18pub struct VersionVector(pub BTreeMap<ReplicaId, u64>);
19
20impl VersionVector {
21 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub fn get(&self, replica: &ReplicaId) -> u64 {
26 self.0.get(replica).copied().unwrap_or(0)
27 }
28
29 pub fn covers_dot(&self, dot: &Dot) -> bool {
30 self.get(&dot.replica) >= dot.counter
31 }
32
33 pub fn covers(&self, other: &VersionVector) -> bool {
34 other.0.iter().all(|(r, c)| self.get(r) >= *c)
35 }
36
37 pub fn add_dot(&mut self, dot: &Dot) {
38 let slot = self.0.entry(dot.replica).or_insert(0);
39 *slot = (*slot).max(dot.counter);
40 }
41
42 pub fn merge(&mut self, other: &VersionVector) {
43 for (r, c) in &other.0 {
44 let slot = self.0.entry(*r).or_insert(0);
45 *slot = (*slot).max(*c);
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use uuid::Uuid;
54
55 fn r(n: u128) -> ReplicaId {
56 ReplicaId(Uuid::from_u128(n))
57 }
58
59 #[test]
60 fn cover_and_merge() {
61 let mut a = VersionVector::new();
62 a.add_dot(&Dot {
63 replica: r(1),
64 counter: 3,
65 });
66 let mut b = VersionVector::new();
67 b.add_dot(&Dot {
68 replica: r(2),
69 counter: 1,
70 });
71 assert!(a.covers_dot(&Dot {
72 replica: r(1),
73 counter: 2
74 }));
75 assert!(!a.covers_dot(&Dot {
76 replica: r(2),
77 counter: 1
78 }));
79 assert!(!a.covers(&b));
80 a.merge(&b);
81 assert!(a.covers(&b));
82 a.add_dot(&Dot {
83 replica: r(1),
84 counter: 1,
85 });
86 assert_eq!(a.get(&r(1)), 3, "add_dot never lowers a counter");
87 }
88
89 #[test]
90 fn serializes_as_a_json_object_keyed_by_uuid() {
91 let mut v = VersionVector::new();
92 v.add_dot(&Dot {
93 replica: r(1),
94 counter: 2,
95 });
96 let json = serde_json::to_string(&v).unwrap();
97 assert_eq!(json, r#"{"00000000-0000-0000-0000-000000000001":2}"#);
98 assert_eq!(serde_json::from_str::<VersionVector>(&json).unwrap(), v);
99 }
100}