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()),
}),
}
}
}