jmbl 0.5.0

A high performance CRDT
Documentation
use crate::mem_use::{MemUsage, MemUser};

use super::{
    list::list_state::ListState, map::map_state::MapState, ops::Op, text::text_state::TextState,
};

pub(crate) trait ObjectState: Clone {
    fn apply_op(&self, op: Op) -> Self {
        self.apply_ops(Some(op))
    }

    fn apply_ops<II: IntoIterator<Item = Op>>(&self, ops: II) -> Self {
        let mut curr = None;
        for op in ops.into_iter() {
            curr = Some(curr.as_ref().unwrap_or(self).apply_op(op));
        }
        curr.unwrap_or_else(|| self.clone())
    }

    fn ops_since(&self, other: Option<&Self>) -> Vec<Op>;
}

#[derive(Clone, Debug)]
pub(crate) enum AnyObjectState {
    List(ListState),
    Text(TextState),
    Map(MapState),
}

impl ObjectState for AnyObjectState {
    fn apply_ops<II: IntoIterator<Item = Op>>(&self, ops: II) -> Self {
        match self {
            AnyObjectState::List(list_state) => AnyObjectState::List(list_state.apply_ops(ops)),
            AnyObjectState::Text(text_state) => AnyObjectState::Text(text_state.apply_ops(ops)),
            AnyObjectState::Map(map_state) => AnyObjectState::Map(map_state.apply_ops(ops)),
        }
    }

    fn ops_since(&self, other: Option<&AnyObjectState>) -> Vec<Op> {
        match (self, other) {
            (AnyObjectState::List(list_state), Some(AnyObjectState::List(other_list_state))) => {
                list_state.ops_since(Some(other_list_state))
            }
            (AnyObjectState::List(list_state), None) => list_state.ops_since(None),
            (AnyObjectState::Text(list_state), Some(AnyObjectState::Text(other_list_state))) => {
                list_state.ops_since(Some(other_list_state))
            }
            (AnyObjectState::Text(list_state), None) => list_state.ops_since(None),
            (AnyObjectState::Map(map_state), Some(AnyObjectState::Map(other_map_state))) => {
                map_state.ops_since(Some(other_map_state))
            }
            (AnyObjectState::Map(map_state), None) => map_state.ops_since(None),
            _ => panic!("Invalid pair of object states to compare"),
        }
    }
}

impl MemUser for AnyObjectState {
    fn mem_use(&self) -> MemUsage {
        MemUsage::Enum {
            name: "ObjectState",
            discriminant: std::mem::size_of::<usize>(),
            min_size: std::mem::size_of::<AnyObjectState>(),
            variant: Box::new(match self {
                AnyObjectState::List(list) => ("List", list.mem_use()),
                AnyObjectState::Text(text) => ("Text", text.mem_use()),
                AnyObjectState::Map(map) => ("Map", map.mem_use()),
            }),
        }
    }
}