jmbl/
object.rs

1use crate::mem_use::{MemUsage, MemUser};
2
3use super::{
4    list::list_state::ListState, map::map_state::MapState, ops::Op, text::text_state::TextState,
5};
6
7pub(crate) trait ObjectState: Clone {
8    fn apply_op(&self, op: Op) -> Self {
9        self.apply_ops(Some(op))
10    }
11
12    fn apply_ops<II: IntoIterator<Item = Op>>(&self, ops: II) -> Self {
13        let mut curr = None;
14        for op in ops.into_iter() {
15            curr = Some(curr.as_ref().unwrap_or(self).apply_op(op));
16        }
17        curr.unwrap_or_else(|| self.clone())
18    }
19
20    fn ops_since(&self, other: Option<&Self>) -> Vec<Op>;
21}
22
23#[derive(Clone, Debug)]
24pub(crate) enum AnyObjectState {
25    List(ListState),
26    Text(TextState),
27    Map(MapState),
28}
29
30impl ObjectState for AnyObjectState {
31    fn apply_ops<II: IntoIterator<Item = Op>>(&self, ops: II) -> Self {
32        match self {
33            AnyObjectState::List(list_state) => AnyObjectState::List(list_state.apply_ops(ops)),
34            AnyObjectState::Text(text_state) => AnyObjectState::Text(text_state.apply_ops(ops)),
35            AnyObjectState::Map(map_state) => AnyObjectState::Map(map_state.apply_ops(ops)),
36        }
37    }
38
39    fn ops_since(&self, other: Option<&AnyObjectState>) -> Vec<Op> {
40        match (self, other) {
41            (AnyObjectState::List(list_state), Some(AnyObjectState::List(other_list_state))) => {
42                list_state.ops_since(Some(other_list_state))
43            }
44            (AnyObjectState::List(list_state), None) => list_state.ops_since(None),
45            (AnyObjectState::Text(list_state), Some(AnyObjectState::Text(other_list_state))) => {
46                list_state.ops_since(Some(other_list_state))
47            }
48            (AnyObjectState::Text(list_state), None) => list_state.ops_since(None),
49            (AnyObjectState::Map(map_state), Some(AnyObjectState::Map(other_map_state))) => {
50                map_state.ops_since(Some(other_map_state))
51            }
52            (AnyObjectState::Map(map_state), None) => map_state.ops_since(None),
53            _ => panic!("Invalid pair of object states to compare"),
54        }
55    }
56}
57
58impl MemUser for AnyObjectState {
59    fn mem_use(&self) -> MemUsage {
60        MemUsage::Enum {
61            name: "ObjectState",
62            discriminant: std::mem::size_of::<usize>(),
63            min_size: std::mem::size_of::<AnyObjectState>(),
64            variant: Box::new(match self {
65                AnyObjectState::List(list) => ("List", list.mem_use()),
66                AnyObjectState::Text(text) => ("Text", text.mem_use()),
67                AnyObjectState::Map(map) => ("Map", map.mem_use()),
68            }),
69        }
70    }
71}