pub struct VClock<K = usize, I = usize>where
K: Eq + Hash + Clone,
I: Add<I, Output = I> + AddAssign<I> + From<u8> + Ord + Default + Clone,{ /* private fields */ }
Expand description
Vector clock with generic types.
Internally, it is just simple hash map containing integers, or at least something you can increase and compare.
The key can be anything which can be hashed and cloned.
The key and counter both need to support Clone as internally,
especially when merging, some copies need to be made. The
implementation tries to call .clone()
as rarely as possible.
Sometimes the Rust compiler can infer the type of the counter,
but it may not always be the case. Type aliases, such as
VClock64
, are here as syntaxic sugar.
§Examples
use vclock::VClock;
let mut c: VClock<&str>=VClock::default();
c.incr(&"a");
c.incr(&"a");
c.incr(&"a");
c.incr(&"a");
c.incr(&"b");
assert_eq!(Some(3), c.get(&"a"));
assert_eq!(Some(0), c.get(&"b"));
assert_eq!(None, c.get(&"c"));
Implementations§
source§impl<K, I> VClock<K, I>
impl<K, I> VClock<K, I>
sourcepub fn new(key: K) -> VClock<K, I>
pub fn new(key: K) -> VClock<K, I>
Initialize a new vector clock with only one contributor. It is useful to avoid the new() then incr() pattern, as it performs both operations at once, without copying anything.
§Examples
use vclock::VClock;
let c = VClock::<&str, u16>::new("foo"); // c is now foo:0
assert_eq!("{len: 1, weight: 1, max: {\"foo\": 0}}", format!("{}", c));
sourcepub fn get(&self, key: &K) -> Option<I>
pub fn get(&self, key: &K) -> Option<I>
Returns the counter associated to a given key.
§Examples
use vclock::VClock;
let mut c = VClock::new("foo"); // c is now foo:0
c.incr(&"foo"); // c is now foo:1
c.incr(&"bar"); // c is now foo:1, bar:0
assert_eq!(1, c.get(&"foo").unwrap());
assert_eq!(0, c.get(&"bar").unwrap());
assert_eq!(None, c.get(&"unknown"));
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements in a VClock.
§Examples
use vclock::VClock;
let mut c = VClock::<&str, u8>::default();
assert_eq!(0, c.len());
c.incr(&"foo");
assert_eq!(1, c.len());
c.incr(&"foo");
assert_eq!(1, c.len());
c.incr(&"bar");
assert_eq!(2, c.len());
sourcepub fn weight(&self) -> I
pub fn weight(&self) -> I
Returns the total of all values, plus the number of values.
This is mostly a debugging feature. You should not use this to compare clocks. If a < b then a.weight() < b.weight() but the reciprocity is not true. However it can be useful to have this information when auditing behavior.
§Examples
use vclock::VClock;
let mut c = VClock::<&str, u32>::default();
assert_eq!(0, c.weight());
c.incr(&"foo");
assert_eq!(1, c.weight());
c.incr(&"foo");
assert_eq!(2, c.weight());
c.incr(&"foo");
assert_eq!(3, c.weight());
c.incr(&"bar");
assert_eq!(4, c.weight());
c.incr(&"bar");
assert_eq!(5, c.weight());
sourcepub fn max(&self) -> Option<(&K, I)>
pub fn max(&self) -> Option<(&K, I)>
Returns the max key,value pair.
This is mostly a debugging feature. You should not use this to compare clocks. If a < b then a.max() <= b.max() but the reciprocity is not true. However it can be useful to have this information when auditing behavior.
§Examples
use vclock::VClock;
let mut c = VClock::default();
assert_eq!(None, c.max());
c.incr(&"foo");
assert_eq!((&"foo", 0), c.max().unwrap());
c.incr(&"foo");
assert_eq!((&"foo", 1), c.max().unwrap());
c.incr(&"bar");
assert_eq!((&"foo", 1), c.max().unwrap());
sourcepub fn incr(&mut self, key: &K)
pub fn incr(&mut self, key: &K)
Increment a vector clock in-place.
§Examples
use vclock::VClock;
let mut c = VClock::<&str, u64>::new("foo"); // c is now foo:0
c.incr(&"foo"); // c is now foo:1
c.incr(&"bar"); // c is now foo:1, bar:0
assert_eq!("{len: 2, weight: 3, max: {\"foo\": 1}}", format!("{}", c));
sourcepub fn next(self, key: &K) -> VClock<K, I>
pub fn next(self, key: &K) -> VClock<K, I>
Increments a vector clock. This is pretty much the same as incr but it takes ownership on the vector clock.
§Examples
use vclock::VClock;
let c1 = VClock::<&str, u16>::new("a");
let c2 = c1.clone().next(&"a").next(&"b");
assert_eq!(1, c2.get(&"a").unwrap());
assert_eq!(0, c2.get(&"b").unwrap());
sourcepub fn merge(&mut self, other: &VClock<K, I>)
pub fn merge(&mut self, other: &VClock<K, I>)
Merge a key with another one, in-place, taking the max of all history points.
If there is a parentship between a and b, just take the greater of both.
§Examples
use vclock::VClock;
let mut c1 = VClock::<&str, u32>::new("a");
let c2 = VClock::<&str, u32>::new("b");
c1.merge(&c2);
assert_eq!(Some(0), c1.get(&"a"));
assert_eq!(Some(0), c1.get(&"b"));
sourcepub fn combine(self, other: &VClock<K, I>) -> VClock<K, I>
pub fn combine(self, other: &VClock<K, I>) -> VClock<K, I>
Combine a key with another one, taking ownership.
If there is a parentship between a and b, just take the greater of both.
§Examples
use vclock::VClock;
let c1 = VClock::new("a");
let c2 = VClock::new("b").next(&"b");
let c3 = VClock::new("c");
let c4 = c1.combine(&c2).combine(&c3);
assert_eq!(0, c4.get(&"a").unwrap());
assert_eq!(1, c4.get(&"b").unwrap());
assert_eq!(0, c4.get(&"c").unwrap());
Trait Implementations§
source§impl<'de, K, I> Deserialize<'de> for VClock<K, I>
impl<'de, K, I> Deserialize<'de> for VClock<K, I>
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
source§impl<K, I> Display for VClock<K, I>
impl<K, I> Display for VClock<K, I>
source§fn fmt(&self, f: &mut Formatter<'_>) -> Result
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Pretty print the vector clock, it does not dump all the data, only a few key values.
§Examples
use vclock::VClock;
let mut c = VClock::<&str, usize>::default();
assert_eq!("{len: 0, weight: 0}", format!("{}", c));
c.incr(&"a");
assert_eq!("{len: 1, weight: 1, max: {\"a\": 0}}", format!("{}", c));
c.incr(&"b");
c.incr(&"b");
assert_eq!("{len: 2, weight: 3, max: {\"b\": 1}}", format!("{}", c));
source§impl<K, I> From<HashMap<K, I>> for VClock<K, I>
impl<K, I> From<HashMap<K, I>> for VClock<K, I>
source§fn from(src: HashMap<K, I>) -> VClock<K, I>
fn from(src: HashMap<K, I>) -> VClock<K, I>
Build a vector clock from a hash map containing u64 values.
§Examples
use vclock::VClock;
use std::collections::HashMap;
let mut m = HashMap::new();
m.insert("a", 3u64);
m.insert("b", 5u64);
let c = VClock::from(m);
assert_eq!(2, c.len());
assert_eq!(3, c.get(&"a").unwrap());
assert_eq!(5, c.get(&"b").unwrap());
source§impl<K, I> From<VClock<K, I>> for HashMap<K, I>
impl<K, I> From<VClock<K, I>> for HashMap<K, I>
source§fn from(src: VClock<K, I>) -> HashMap<K, I>
fn from(src: VClock<K, I>) -> HashMap<K, I>
Build a vector clock from a hash map containing u64 values.
§Examples
use vclock::VClock;
use std::collections::HashMap;
let mut c = VClock::default();
c.incr(&"a");
c.incr(&"a");
c.incr(&"b");
let m = HashMap::from(c);
assert_eq!(2, m.len());
assert_eq!(Some(&1), m.get(&"a"));
assert_eq!(Some(&0), m.get(&"b"));
source§impl<K, I> PartialEq for VClock<K, I>
impl<K, I> PartialEq for VClock<K, I>
source§impl<K, I> PartialOrd for VClock<K, I>
impl<K, I> PartialOrd for VClock<K, I>
Vector clocks are partially ordered, and this is exactly what they are useful for. If the order is explicitly returned, it means one can fast-forward or fast-rewind from one point to the other in history. If not, that is, if None is returned, it means there is a conflict, and no way to directly go to one point from the other.
source§fn partial_cmp(&self, other: &Self) -> Option<Ordering>
fn partial_cmp(&self, other: &Self) -> Option<Ordering>
Compares the vector clock with another one. Note that really, this is a partial order, if both a<=b and a>=b return false, it means there is no direct parentship link between clocks.
§Examples
use vclock::VClock;
use std::cmp::Ordering;
// Two vector clocks holding same values are equal.
let mut c1 = VClock::<&str, u32>::new("a");
let mut c2 = VClock::<&str, u32>::new("a");
assert_eq!(Some(Ordering::Equal), c1.partial_cmp(&c2));
assert!(c1 <= c2);
// Two vector clocks with a direct parentship are ordered.
c2.incr(&"a");
assert_eq!(Some(Ordering::Less), c1.partial_cmp(&c2));
assert_eq!(Some(Ordering::Greater), c2.partial_cmp(&c1));
assert!(c1 < c2);
assert!(c2 > c1);
// Two vector clocks without a direct parentship are not ordered.
c1.incr(&"b");
assert_eq!(None, c1.partial_cmp(&c2));
assert_eq!(None, c2.partial_cmp(&c1));
assert!(!(c1 < c2));
assert!(!(c2 > c1));
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self
and other
) and is used by the <=
operator. Read more