cvrdt_exposition/
two_phase_set.rs1use crate::traits::{Grow, Shrink};
2use std::collections::HashSet;
3use std::hash::Hash;
4
5#[derive(Debug, Clone)]
40pub struct TwoPhaseSet<X: Clone + Eq + Hash> {
41 pub added: HashSet<X>,
43 pub removed: HashSet<X>,
45}
46
47impl<X: Clone + Eq + Hash> Grow for TwoPhaseSet<X> {
48 type Payload = (HashSet<X>, HashSet<X>);
49 type Update = X;
50 type Query = X;
51 type Value = bool;
52
53 fn new(payload: Self::Payload) -> Self {
54 TwoPhaseSet {
55 added: payload.0,
56 removed: payload.1,
57 }
58 }
59 fn payload(&self) -> Self::Payload {
60 (self.added.clone(), self.removed.clone())
61 }
62 fn add(&mut self, update: Self::Update) {
63 self.added.insert(update);
64 }
65 fn le(&self, other: &Self) -> bool {
66 self.added.is_subset(&other.added) && self.removed.is_subset(&other.removed)
67 }
68 fn merge(&self, other: &Self) -> Self {
69 TwoPhaseSet {
70 added: self.added.union(&other.added).cloned().collect(),
71 removed: self.removed.union(&other.removed).cloned().collect(),
72 }
73 }
74 fn query(&self, query: &Self::Query) -> Self::Value {
75 self.added.contains(query) && !self.removed.contains(query)
76 }
77}
78
79impl<X: Clone + Eq + Hash> Shrink for TwoPhaseSet<X> {
80 fn del(&mut self, x: X) {
81 assert!(
82 self.query(&x),
83 "Only allowed for elements contained in 2PSet"
84 );
85 self.removed.insert(x);
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use crate::properties::{grow, shrink};
93 use proptest::prelude::*;
94
95 static MAX_SIZE: usize = 100;
96
97 fn cvrdt() -> impl Strategy<Value = TwoPhaseSet<String>> {
98 (
99 prop::collection::hash_set(any::<String>(), 0..MAX_SIZE),
100 prop::collection::hash_set(any::<String>(), 0..MAX_SIZE),
101 )
102 .prop_map(|(added, removed)| TwoPhaseSet { added, removed })
103 }
104
105 fn cvrdt_and_addend() -> impl Strategy<Value = (TwoPhaseSet<String>, String)> {
106 (cvrdt(), ".*")
107 }
108
109 fn cvrdt_and_subtrahend() -> impl Strategy<Value = (TwoPhaseSet<i8>, i8)> {
110 (
111 prop::collection::hash_set(any::<i8>(), 0..MAX_SIZE),
112 prop::collection::hash_set(any::<i8>(), 0..MAX_SIZE),
113 any::<i8>(),
114 )
115 .prop_flat_map(|(mut added, mut removed, x)| {
116 added.insert(x);
117 removed.remove(&x);
118 let t = TwoPhaseSet { added, removed };
119 (Just(t), Just(x))
120 })
121 }
122
123 grow!(cvrdt, cvrdt_and_addend);
124 shrink!(cvrdt_and_subtrahend);
125}