pub struct Map<K: Ord, V: Val<A>, A: Ord + Hash> { /* private fields */ }
Expand description
Map CRDT - Supports Composition of CRDT’s with reset-remove semantics.
Reset-remove means that if one replica removes an entry while another actor concurrently edits that entry, once we sync these two maps, we will see that the entry is still in the map but all edits seen by the removing actor will be gone.
See examples/reset_remove.rs for an example of reset-remove semantics in action.
Implementations§
source§impl<K: Ord, V: Val<A>, A: Ord + Hash + Clone> Map<K, V, A>
impl<K: Ord, V: Val<A>, A: Ord + Hash + Clone> Map<K, V, A>
sourcepub fn is_empty(&self) -> ReadCtx<bool, A>
pub fn is_empty(&self) -> ReadCtx<bool, A>
Returns true if the map has no entries, false otherwise
sourcepub fn update<F>(&self, key: impl Into<K>, ctx: AddCtx<A>, f: F) -> Op<K, V, A>where
F: FnOnce(&V, AddCtx<A>) -> V::Op,
pub fn update<F>(&self, key: impl Into<K>, ctx: AddCtx<A>, f: F) -> Op<K, V, A>where F: FnOnce(&V, AddCtx<A>) -> V::Op,
Update a value under some key.
If the key is not present in the map, the updater will be given the
result of V::default()
. The default
value is used to ensure
eventual consistency since our Map
’s values are CRDTs themselves.
The impl Into<K>
bound provides a nice way of providing an input key that
can easily convert to the Map
’s key. For example, we can call this function
with "hello": &str
and it can be converted to String
.
sourcepub fn rm(&self, key: impl Into<K>, ctx: RmCtx<A>) -> Op<K, V, A>
pub fn rm(&self, key: impl Into<K>, ctx: RmCtx<A>) -> Op<K, V, A>
Remove an entry from the Map
The impl Into<K>
bound provides a nice way of providing an input key that
can easily convert to the Map
’s key. For example, we can call this function
with "hello": &str
and it can be converted to String
.
sourcepub fn keys(&self) -> impl Iterator<Item = ReadCtx<&K, A>>
pub fn keys(&self) -> impl Iterator<Item = ReadCtx<&K, A>>
Gets an iterator over the keys of the Map
.
Examples
use crdts::Map;
use crdts::MVReg;
use crdts::CmRDT;
type Actor = &'static str;
type Key = &'static str;
let actor = "actor";
let mut map: Map<i32, MVReg<Key, Actor>, Actor> = Map::new();
let add_ctx = map.read_ctx().derive_add_ctx(actor);
map.apply(map.update(100, add_ctx, |v, a| v.write("foo", a)));
let add_ctx = map.read_ctx().derive_add_ctx(actor);
map.apply(map.update(50, add_ctx, |v, a| v.write("bar", a)));
let add_ctx = map.read_ctx().derive_add_ctx(actor);
map.apply(map.update(200, add_ctx, |v, a| v.write("baz", a)));
let mut keys: Vec<_> = map.keys().map(|key_ctx| *key_ctx.val).collect();
keys.sort();
assert_eq!(keys, &[50, 100, 200]);
sourcepub fn values(&self) -> impl Iterator<Item = ReadCtx<&V, A>>
pub fn values(&self) -> impl Iterator<Item = ReadCtx<&V, A>>
Gets an iterator over the values of the Map
.
Examples
use crdts::Map;
use crdts::MVReg;
use crdts::CmRDT;
type Actor = &'static str;
type Key = &'static str;
let actor = "actor";
let mut map: Map<i32, MVReg<Key, Actor>, Actor> = Map::new();
let add_ctx = map.read_ctx().derive_add_ctx(actor);
map.apply(map.update(100, add_ctx, |v, a| v.write("foo", a)));
let add_ctx = map.read_ctx().derive_add_ctx(actor);
map.apply(map.update(50, add_ctx, |v, a| v.write("bar", a)));
let add_ctx = map.read_ctx().derive_add_ctx(actor);
map.apply(map.update(200, add_ctx, |v, a| v.write("baz", a)));
let mut values: Vec<_> = map
.values()
.map(|val_ctx| val_ctx.val.read().val[0])
.collect();
values.sort();
assert_eq!(values, &["bar", "baz", "foo"]);
sourcepub fn iter(&self) -> impl Iterator<Item = ReadCtx<(&K, &V), A>>
pub fn iter(&self) -> impl Iterator<Item = ReadCtx<(&K, &V), A>>
Gets an iterator over the entries of the Map
.
Examples
use crdts::Map;
use crdts::MVReg;
use crdts::CmRDT;
type Actor = &'static str;
type Key = &'static str;
let actor = "actor";
let mut map: Map<i32, MVReg<Key, Actor>, Actor> = Map::new();
let add_ctx = map.read_ctx().derive_add_ctx(actor);
map.apply(map.update(100, add_ctx, |v, a| v.write("foo", a)));
let add_ctx = map.read_ctx().derive_add_ctx(actor);
map.apply(map.update(50, add_ctx, |v, a| v.write("bar", a)));
let add_ctx = map.read_ctx().derive_add_ctx(actor);
map.apply(map.update(200, add_ctx, |v, a| v.write("baz", a)));
let mut items: Vec<_> = map
.iter()
.map(|item_ctx| (*item_ctx.val.0, item_ctx.val.1.read().val[0]))
.collect();
items.sort();
assert_eq!(items, &[(50, "bar"), (100, "foo"), (200, "baz")]);
Trait Implementations§
source§impl<K: Ord, V: Val<A> + Debug, A: Ord + Hash + Clone + Debug> CmRDT for Map<K, V, A>
impl<K: Ord, V: Val<A> + Debug, A: Ord + Hash + Clone + Debug> CmRDT for Map<K, V, A>
§type Op = Op<K, V, A>
type Op = Op<K, V, A>
§type Validation = CmRDTValidation<V, A>
type Validation = CmRDTValidation<V, A>
validate_op
.source§fn validate_op(&self, op: &Self::Op) -> Result<(), Self::Validation>
fn validate_op(&self, op: &Self::Op) -> Result<(), Self::Validation>
source§impl<K: Ord + Clone + Debug, V: Val<A> + CvRDT + Debug, A: Ord + Hash + Clone + Debug> CvRDT for Map<K, V, A>
impl<K: Ord + Clone + Debug, V: Val<A> + CvRDT + Debug, A: Ord + Hash + Clone + Debug> CvRDT for Map<K, V, A>
§type Validation = CvRDTValidation<K, V, A>
type Validation = CvRDTValidation<K, V, A>
validate_merge
.