#![allow(dead_code)]
use std::collections::HashMap;
#[derive(Debug, Clone, Default, PartialEq)]
pub struct VersionVectorV2 {
clocks: HashMap<String, u64>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VvRelation {
Before,
After,
Equal,
Concurrent,
}
impl VersionVectorV2 {
pub fn new() -> Self {
VersionVectorV2 { clocks: HashMap::new() }
}
pub fn increment(&mut self, node: &str) {
let c = self.clocks.entry(node.to_owned()).or_insert(0);
*c += 1;
}
pub fn get(&self, node: &str) -> u64 {
*self.clocks.get(node).unwrap_or(&0)
}
pub fn merge(&mut self, other: &VersionVectorV2) {
for (node, &clock) in &other.clocks {
let entry = self.clocks.entry(node.clone()).or_insert(0);
*entry = (*entry).max(clock);
}
}
pub fn relation(&self, other: &VersionVectorV2) -> VvRelation {
let all_nodes: std::collections::HashSet<&str> = self
.clocks
.keys()
.chain(other.clocks.keys())
.map(|s| s.as_str())
.collect();
let mut self_le = true;
let mut other_le = true;
for node in all_nodes {
let a = self.get(node);
let b = other.get(node);
if a > b {
other_le = false;
}
if b > a {
self_le = false;
}
}
match (self_le, other_le) {
(true, true) => VvRelation::Equal,
(true, false) => VvRelation::Before,
(false, true) => VvRelation::After,
(false, false) => VvRelation::Concurrent,
}
}
pub fn node_count(&self) -> usize {
self.clocks.len()
}
}
pub fn new_version_vector_v2() -> VersionVectorV2 {
VersionVectorV2::new()
}
pub fn vv_increment(vv: &mut VersionVectorV2, node: &str) {
vv.increment(node);
}
pub fn vv_merge(base: &mut VersionVectorV2, other: &VersionVectorV2) {
base.merge(other);
}
pub fn vv_relation(a: &VersionVectorV2, b: &VersionVectorV2) -> VvRelation {
a.relation(b)
}
pub fn vv_get(vv: &VersionVectorV2, node: &str) -> u64 {
vv.get(node)
}
pub fn vv_node_count(vv: &VersionVectorV2) -> usize {
vv.node_count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_increment() {
let mut vv = new_version_vector_v2();
vv_increment(&mut vv, "A");
vv_increment(&mut vv, "A");
assert_eq!(vv_get(&vv, "A"), 2 );
}
#[test]
fn test_default_zero() {
let vv = new_version_vector_v2();
assert_eq!(vv_get(&vv, "X"), 0 );
}
#[test]
fn test_equal() {
let mut a = new_version_vector_v2();
let mut b = new_version_vector_v2();
vv_increment(&mut a, "N");
vv_increment(&mut b, "N");
assert_eq!(vv_relation(&a, &b), VvRelation::Equal );
}
#[test]
fn test_before() {
let a = new_version_vector_v2();
let mut b = new_version_vector_v2();
vv_increment(&mut b, "N");
assert_eq!(vv_relation(&a, &b), VvRelation::Before );
}
#[test]
fn test_after() {
let mut a = new_version_vector_v2();
let b = new_version_vector_v2();
vv_increment(&mut a, "N");
assert_eq!(vv_relation(&a, &b), VvRelation::After );
}
#[test]
fn test_concurrent() {
let mut a = new_version_vector_v2();
let mut b = new_version_vector_v2();
vv_increment(&mut a, "A");
vv_increment(&mut b, "B");
assert_eq!(vv_relation(&a, &b), VvRelation::Concurrent );
}
#[test]
fn test_merge() {
let mut a = new_version_vector_v2();
let mut b = new_version_vector_v2();
vv_increment(&mut a, "X");
vv_increment(&mut b, "Y");
vv_merge(&mut a, &b);
assert_eq!(vv_get(&a, "Y"), 1 );
assert_eq!(vv_get(&a, "X"), 1);
}
#[test]
fn test_merge_takes_max() {
let mut a = new_version_vector_v2();
let mut b = new_version_vector_v2();
vv_increment(&mut a, "N");
vv_increment(&mut a, "N");
vv_increment(&mut b, "N");
vv_merge(&mut a, &b);
assert_eq!(vv_get(&a, "N"), 2 );
}
#[test]
fn test_node_count() {
let mut vv = new_version_vector_v2();
vv_increment(&mut vv, "A");
vv_increment(&mut vv, "B");
assert_eq!(vv_node_count(&vv), 2 );
}
}