1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use std::cmp::{Ordering, PartialOrd};
use std::hash::{Hash, Hasher};
use serde::{Deserialize, Serialize};
use crate::quickcheck::{Arbitrary, Gen};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Dot<A> {
pub actor: A,
pub counter: u64,
}
impl<A: Clone> Dot<A> {
pub fn new(actor: A, counter: u64) -> Self {
Self { actor, counter }
}
pub fn inc(&self) -> Self {
Self {
actor: self.actor.clone(),
counter: self.counter + 1,
}
}
pub fn apply_inc(&mut self) {
self.counter += 1;
}
}
impl<A: Copy> Copy for Dot<A> {}
impl<A: PartialEq> PartialEq for Dot<A> {
fn eq(&self, other: &Self) -> bool {
self.actor == other.actor && self.counter == other.counter
}
}
impl<A: Eq> Eq for Dot<A> {}
impl<A: Hash> Hash for Dot<A> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.actor.hash(state);
self.counter.hash(state);
}
}
impl<A: PartialOrd> PartialOrd for Dot<A> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.actor == other.actor {
self.counter.partial_cmp(&other.counter)
} else {
None
}
}
}
impl<A: Arbitrary + Clone> Arbitrary for Dot<A> {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
Dot {
actor: A::arbitrary(g),
counter: u64::arbitrary(g) % 50,
}
}
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
let mut shrunk_dots = Vec::new();
if self.counter > 0 {
shrunk_dots.push(Self::new(self.actor.clone(), self.counter - 1));
}
Box::new(shrunk_dots.into_iter())
}
}
#[cfg(test)]
mod test {
use super::*;
use quickcheck::quickcheck;
quickcheck! {
fn inc_increments_only_the_counter(dot: Dot<u8>) -> bool {
dot.inc() == Dot::new(dot.actor, dot.counter + 1)
}
fn test_partial_order(a: Dot<u8>, b: Dot<u8>) -> bool {
let cmp_ab = a.partial_cmp(&b);
let cmp_ba = b.partial_cmp(&a);
match (cmp_ab, cmp_ba) {
(None, None) => a.actor != b.actor,
(Some(Ordering::Less), Some(Ordering::Greater)) => a.actor == b.actor && a.counter < b.counter,
(Some(Ordering::Greater), Some(Ordering::Less)) => a.actor == b.actor && a.counter > b.counter,
(Some(Ordering::Equal), Some(Ordering::Equal)) => a.actor == b.actor && a.counter == b.counter,
_ => false
}
}
}
}