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
extern crate alloc;
use alloc::collections::{BTreeMap, BTreeSet};
use super::super::{DotSet, DotStore};
use super::{Dot, DotFun};
impl<V: Clone> DotStore for DotFun<V> {
fn dots(&self) -> impl Iterator<Item = Dot> + '_ {
// `BTreeMap` keys are already ascending dots, each once.
self.entries.keys().copied()
}
fn is_bottom(&self) -> bool {
self.entries.is_empty()
}
fn causal_merge(&self, self_context: &DotSet, other: &Self, other_context: &DotSet) -> Self {
// The survivor law, per dot, content following the dot. A dot in both
// stores carries equal content by the honest basis (keep-self, equal
// by basis; see the type rustdoc for the discipline and its Byzantine
// caveat), so we keep self's; a dot in one store and unseen on the
// other side survives with its own content; a dot seen and dropped on
// the other side is superseded.
let mut entries = BTreeMap::new();
for (&dot, value) in &self.entries {
let in_both = other.entries.contains_key(&dot);
if Self::survives(in_both, other_context.contains(dot)) {
let _ = entries.insert(dot, value.clone());
}
}
for (&dot, value) in &other.entries {
if self.entries.contains_key(&dot) {
continue; // already carried, self's content kept above
}
// Other's dot, unseen here: `in_both` is false (self did not carry
// it above), so survival reduces to "self never saw it".
if Self::survives(false, self_context.contains(dot)) {
let _ = entries.insert(dot, value.clone());
}
}
Self { entries }
}
fn restrict(&self, roster: impl IntoIterator<Item = u32>) -> Self {
let roster: BTreeSet<u32> = roster.into_iter().collect();
let entries = self
.entries
.iter()
.filter(|(dot, _)| roster.contains(&dot.station()))
.map(|(&dot, value)| (dot, value.clone()))
.collect();
Self { entries }
}
fn novel_to(&self, context: &DotSet) -> Self {
// The sub-store of dots the peer context has never seen, content
// following each dot (the S97 anti-entropy selection).
let entries = self
.entries
.iter()
.filter(|(dot, _)| !context.contains(**dot))
.map(|(&dot, value)| (dot, value.clone()))
.collect();
Self { entries }
}
}