Skip to main content

ossa_crdt/map/
twopmap.rs

1use im::{OrdMap, OrdSet};
2use ossa_typeable::Typeable;
3use serde::de::{MapAccess, Visitor};
4use serde::ser::{SerializeStruct, Serializer};
5use serde::{Deserialize, Serialize};
6use std::fmt::{self, Debug};
7use std::marker::PhantomData;
8
9use crate::time::CausalState;
10use crate::CRDT;
11
12/// Two phase map.
13/// Invariant: All keys must be unique.
14#[derive(Clone, Typeable)]
15pub struct TwoPMap<K, V> {
16    // JP: Drop `K`?
17    map: OrdMap<K, V>,
18    tombstones: OrdSet<K>,
19}
20
21// TODO: Standardized serialization.
22impl<K: Serialize + Ord + Clone, V: Serialize + Clone> Serialize for TwoPMap<K, V> {
23    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
24    where
25        S: Serializer,
26    {
27        let mut s = serializer.serialize_struct("TwoPMap", 2)?;
28        s.serialize_field("map", &self.map)?;
29        s.serialize_field("tombstones", &self.tombstones)?;
30        s.end()
31    }
32}
33
34impl<'d, K: Clone + Ord + Deserialize<'d>, V: Clone + Deserialize<'d>> Deserialize<'d>
35    for TwoPMap<K, V>
36{
37    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
38    where
39        D: serde::Deserializer<'d>,
40    {
41        struct SVisitor<K, V>(PhantomData<(K, V)>);
42
43        #[derive(Deserialize)]
44        #[serde(field_identifier, rename_all = "lowercase")]
45        enum Field {
46            Map,
47            Tombstones,
48        }
49
50        impl<'d, K: Ord + Clone + Deserialize<'d>, V: Clone + Deserialize<'d>> Visitor<'d>
51            for SVisitor<K, V>
52        {
53            type Value = TwoPMap<K, V>;
54
55            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
56                formatter.write_str("struct TwoPMap")
57            }
58
59            fn visit_map<M>(self, mut m: M) -> Result<TwoPMap<K, V>, M::Error>
60            where
61                M: MapAccess<'d>,
62            {
63                let mut map = None;
64                let mut tombstones = None;
65                while let Some(key) = m.next_key()? {
66                    match key {
67                        Field::Map => {
68                            if map.is_some() {
69                                return Err(serde::de::Error::duplicate_field("map"));
70                            }
71                            map = Some(m.next_value()?);
72                        }
73                        Field::Tombstones => {
74                            if tombstones.is_some() {
75                                return Err(serde::de::Error::duplicate_field("tombstones"));
76                            }
77                            tombstones = Some(m.next_value()?);
78                        }
79                    }
80                }
81
82                let map = map.ok_or_else(|| serde::de::Error::missing_field("map"))?;
83                let tombstones =
84                    tombstones.ok_or_else(|| serde::de::Error::missing_field("tombstones"))?;
85
86                Ok(TwoPMap { map, tombstones })
87            }
88        }
89
90        deserializer.deserialize_struct("TwoPMap", &["map", "tombstones"], SVisitor(PhantomData))
91    }
92}
93
94impl<K: Ord + Debug, V: Debug> Debug for TwoPMap<K, V> {
95    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
96        self.map.fmt(f)
97    }
98}
99
100// TODO: Define CBOR properly
101#[derive(Debug, Serialize, Deserialize)]
102pub enum TwoPMapOp<K, V, Op> {
103    Insert { key: K, value: V },
104    Apply { key: K, operation: Op },
105    Delete { key: K },
106}
107
108impl<K, V, Op> TwoPMapOp<K, V, Op> {
109    fn key(&self) -> &K {
110        match self {
111            TwoPMapOp::Insert { key, .. } => key,
112            TwoPMapOp::Apply { key, .. } => key,
113            TwoPMapOp::Delete { key } => key,
114        }
115    }
116}
117
118impl<K: Ord + Clone, V: CRDT<Time = K> + Clone> CRDT for TwoPMap<K, V> {
119    type Op = TwoPMapOp<K, V, V::Op>;
120    type Time = V::Time; // JP: Newtype wrap `struct TwoPMapId<V>(V::Time)`?
121
122    fn apply<CS: CausalState<Time = Self::Time>>(self, st: &CS, op: Self::Op) -> Self {
123        // Check if deleted.
124        let is_deleted = {
125            let key = op.key();
126            self.tombstones.contains(key)
127        };
128        if is_deleted {
129            self
130        } else {
131            match op {
132                TwoPMapOp::Insert { key, value } => {
133                    let TwoPMap { map, tombstones } = self;
134                    let map = map.update_with(key, value, |_, _| {
135                        unreachable!("Invariant violated. Key already exists in TwoPMap.");
136                    });
137
138                    TwoPMap { map, tombstones }
139                }
140                TwoPMapOp::Apply { key, operation } => {
141                    let TwoPMap { map, tombstones } = self;
142                    let map = map.alter(|v| {
143                        if let Some(v) = v {
144                            Some(v.apply(st, operation))
145                        } else {
146                            unreachable!("Invariant violated. Key must already exist when applyting an update to a TwoPMap.")
147                        }
148                    }, key);
149
150                    TwoPMap { map, tombstones }
151                }
152                TwoPMapOp::Delete { key } => {
153                    let TwoPMap { map, tombstones } = self;
154                    let map = map.without(&key);
155                    let tombstones = tombstones.update(key);
156
157                    TwoPMap { map, tombstones }
158                }
159            }
160        }
161    }
162}
163
164impl<K: Ord, V: CRDT> TwoPMap<K, V> {
165    pub fn new() -> TwoPMap<K, V> {
166        TwoPMap {
167            map: OrdMap::new(),
168            tombstones: OrdSet::new(),
169        }
170    }
171
172    pub fn get(&self, key: &K) -> Option<&V> {
173        self.map.get(key)
174    }
175
176    pub fn iter(&self) -> im::ordmap::Iter<'_, K, V> {
177        self.map.iter()
178    }
179
180    pub fn insert(key: K, value: V) -> TwoPMapOp<K, V, V::Op> {
181        TwoPMapOp::Insert { key, value }
182    }
183}
184
185// impl<'a, T, V: CRDT> Functor<'a, T> for TwoPMapOp<T, V>
186// where
187//     V::Op<T>: for<S> Functor<'a, T, Target<S> = V::Op<S>>,
188// {
189//     type Target<S> = TwoPMapOp<S, V>;
190//
191//     fn fmap<B, F>(self, f: F) -> Self::Target<B>
192//     where
193//         F: Fn(T) -> B + 'a
194//     {
195//         match self {
196//             TwoPMapOp::Insert { key, value } => {
197//                 TwoPMapOp::Insert {: CRDT
198//                     key: f(key),
199//                     value,
200//                 }
201//             }
202//             TwoPMapOp::Apply { key, operation } => {
203//                 let operation: V::Op<B> = operation.fmap::<B, _>(f);
204//                 TwoPMapOp::Apply {
205//                     key: f(key),
206//                     operation,
207//                 }
208//             }
209//             TwoPMapOp::Delete { key } => {
210//                 TwoPMapOp::Delete { key: f(key) }
211//             }
212//         }
213//     }
214// }
215
216// impl<K, L, V, Op> OperationFunctor<K, L> for TwoPMapOp<K, V, Op>
217// where
218//     Op: OperationFunctor<K, L, Target<L> = Op>,
219// {
220//     type Target<Time> = TwoPMapOp<Time, V, Op>;
221//
222//     fn fmap(self, f: impl Fn(K) -> L) -> Self::Target<L> {
223//         match self {
224//             TwoPMapOp::Insert { key, value } => {
225//                 TwoPMapOp::Insert {
226//                     key: f(key),
227//                     value,
228//                 }
229//             }
230//             TwoPMapOp::Apply { key, operation } => {
231//                 let key = f(key);
232//                 let operation = operation.fmap(f);
233//                 TwoPMapOp::Apply {
234//                     key,
235//                     operation,
236//                 }
237//             }
238//             TwoPMapOp::Delete { key } => {
239//                 TwoPMapOp::Delete { key: f(key) }
240//             }
241//         }
242//     }
243// }