use crate::Mergeable;
use std::collections::BTreeMap;
#[derive(Clone, PartialEq, Debug)]
pub struct ConvergentMap<K: Ord + Clone, M: Mergeable> {
entries: BTreeMap<K, M>,
}
impl<K: Ord + Clone, M: Mergeable> Default for ConvergentMap<K, M> {
fn default() -> Self {
Self {
entries: BTreeMap::new(),
}
}
}
impl<K: Ord + Clone, M: Mergeable> ConvergentMap<K, M> {
pub fn new() -> Self {
Self::default()
}
pub fn entry_or(&mut self, key: K, init: impl FnOnce() -> M) -> &mut M {
self.entries.entry(key).or_insert_with(init)
}
pub fn get(&self, key: &K) -> Option<&M> {
self.entries.get(key)
}
pub fn iter(&self) -> impl Iterator<Item = (&K, &M)> {
self.entries.iter()
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn merge(&mut self, other: &Self) {
for (k, m) in &other.entries {
match self.entries.get_mut(k) {
Some(mine) => mine.merge(m),
None => {
self.entries.insert(k.clone(), m.clone());
}
}
}
}
pub fn expire_before(&mut self, cutoff: &K) {
self.entries = self.entries.split_off(cutoff);
}
pub fn count(&self) -> u64 {
self.entries
.values()
.fold(0u64, |a, m| a.saturating_add(m.count()))
}
}
impl<K: Ord + Clone + AsRef<[u8]>, M: Mergeable> ConvergentMap<K, M> {
pub fn encode(&self) -> Vec<u8> {
let mut out = Vec::new();
out.extend_from_slice(&(self.entries.len() as u32).to_le_bytes());
for (k, m) in &self.entries {
let kb = k.as_ref();
out.extend_from_slice(&(kb.len() as u32).to_le_bytes());
out.extend_from_slice(kb);
let mb = m.encode();
out.extend_from_slice(&(mb.len() as u32).to_le_bytes());
out.extend_from_slice(&mb);
}
out
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct Replicated<M: Mergeable> {
entries: BTreeMap<u64, M>,
}
impl<M: Mergeable> Default for Replicated<M> {
fn default() -> Self {
Self {
entries: BTreeMap::new(),
}
}
}
impl<M: Mergeable> Replicated<M> {
pub fn new() -> Self {
Self::default()
}
pub fn local_mut(&mut self, replica: u64, init: impl FnOnce() -> M) -> &mut M {
self.entries.entry(replica).or_insert_with(init)
}
pub fn join(&mut self, other: &Self) {
for (r, m) in &other.entries {
match self.entries.get(r) {
Some(mine) if mine.count() >= m.count() => {}
_ => {
self.entries.insert(*r, m.clone());
}
}
}
}
pub fn global(&self, empty: impl FnOnce() -> M) -> M {
let mut g = empty();
for m in self.entries.values() {
g.merge(m);
}
g
}
pub fn encode(&self) -> Vec<u8> {
let mut out = Vec::new();
out.extend_from_slice(&(self.entries.len() as u32).to_le_bytes());
for (r, m) in &self.entries {
out.extend_from_slice(&r.to_le_bytes());
let mb = m.encode();
out.extend_from_slice(&(mb.len() as u32).to_le_bytes());
out.extend_from_slice(&mb);
}
out
}
}
#[derive(Clone, Debug)]
pub struct Deltas<M: Mergeable> {
full: M,
pending: M,
make_empty: fn() -> M,
}
impl<M: Mergeable> Deltas<M> {
pub fn new(make_empty: fn() -> M) -> Self {
Self {
full: make_empty(),
pending: make_empty(),
make_empty,
}
}
pub fn apply(&mut self, op: impl Fn(&mut M)) {
op(&mut self.full);
op(&mut self.pending);
}
pub fn full(&self) -> &M {
&self.full
}
pub fn take_delta(&mut self) -> M {
core::mem::replace(&mut self.pending, (self.make_empty)())
}
pub fn merge_delta(&mut self, delta: &M) {
self.full.merge(delta);
}
}