loro_internal/delta/
map_delta.rs

1use std::{
2    hash::Hash,
3    sync::Weak,
4};
5
6use fxhash::FxHashMap;
7use loro_common::IdLp;
8use serde::{ser::SerializeStruct, Serialize};
9
10use crate::{
11    change::Lamport, handler::ValueOrHandler, id::PeerID, span::HasLamport, InternalString, LoroDocInner, LoroValue,
12};
13
14#[derive(Default, Debug, Clone, Serialize)]
15pub struct MapDelta {
16    /// If the value is none, it's a uncreate op that should remove the entry from the
17    /// map container.
18    pub updated: FxHashMap<InternalString, Option<MapValue>>,
19}
20
21#[derive(Debug, Clone)]
22pub struct MapValue {
23    pub value: Option<LoroValue>,
24    pub lamp: Lamport,
25    pub peer: PeerID,
26}
27
28impl Ord for MapValue {
29    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
30        self.lamp
31            .cmp(&other.lamp)
32            .then_with(|| self.peer.cmp(&other.peer))
33    }
34}
35
36impl PartialOrd for MapValue {
37    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
38        Some(self.cmp(other))
39    }
40}
41
42impl PartialEq for MapValue {
43    fn eq(&self, other: &Self) -> bool {
44        self.lamp == other.lamp && self.peer == other.peer
45    }
46}
47
48impl Eq for MapValue {}
49
50impl MapValue {
51    pub fn idlp(&self) -> IdLp {
52        IdLp::new(self.peer, self.lamp)
53    }
54}
55
56#[derive(Default, Debug, Clone)]
57pub struct ResolvedMapDelta {
58    pub updated: FxHashMap<InternalString, ResolvedMapValue>,
59}
60
61#[derive(Debug, Clone)]
62pub struct ResolvedMapValue {
63    pub value: Option<ValueOrHandler>,
64    pub idlp: IdLp,
65}
66
67impl ResolvedMapValue {
68    pub(crate) fn from_map_value(v: MapValue, doc: &Weak<LoroDocInner>) -> Self {
69        let doc = &doc.upgrade().unwrap();
70        ResolvedMapValue {
71            idlp: IdLp::new(v.peer, v.lamp),
72            value: v.value.map(|v| ValueOrHandler::from_value(v, doc)),
73        }
74    }
75
76    /// This is used to indicate that the entry is unset. (caused by checkout to before the entry is created)
77    pub fn new_unset() -> Self {
78        ResolvedMapValue {
79            idlp: IdLp::new(PeerID::default(), Lamport::MAX),
80            value: None,
81        }
82    }
83}
84
85impl MapDelta {
86    pub(crate) fn compose(mut self, x: MapDelta) -> MapDelta {
87        for (k, v) in x.updated.into_iter() {
88            if let Some(old) = self.updated.get_mut(&k) {
89                if &v > old {
90                    *old = v;
91                }
92            } else {
93                self.updated.insert(k, v);
94            }
95        }
96        self
97    }
98
99    #[inline]
100    pub fn new() -> Self {
101        MapDelta {
102            updated: FxHashMap::default(),
103        }
104    }
105
106    #[inline]
107    pub fn with_entry(mut self, key: InternalString, map_value: MapValue) -> Self {
108        self.updated.insert(key, Some(map_value));
109        self
110    }
111}
112
113impl ResolvedMapDelta {
114    pub(crate) fn compose(&self, x: ResolvedMapDelta) -> ResolvedMapDelta {
115        let mut updated = self.updated.clone();
116        for (k, v) in x.updated.into_iter() {
117            if let Some(old) = updated.get_mut(&k) {
118                if v.idlp > old.idlp {
119                    *old = v;
120                }
121            } else {
122                updated.insert(k, v);
123            }
124        }
125        ResolvedMapDelta { updated }
126    }
127
128    #[inline]
129    pub fn new() -> Self {
130        ResolvedMapDelta {
131            updated: FxHashMap::default(),
132        }
133    }
134
135    #[inline]
136    pub fn with_entry(mut self, key: InternalString, map_value: ResolvedMapValue) -> Self {
137        self.updated.insert(key, map_value);
138        self
139    }
140
141    pub(crate) fn transform(&mut self, b: &ResolvedMapDelta, left_prior: bool) {
142        for (k, _) in b.updated.iter() {
143            if !left_prior {
144                self.updated.remove(k);
145            }
146        }
147    }
148}
149
150impl Hash for MapValue {
151    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
152        // value is not being hashed
153        self.peer.hash(state);
154        self.lamp.hash(state);
155    }
156}
157
158impl HasLamport for MapValue {
159    fn lamport(&self) -> Lamport {
160        self.lamp
161    }
162}
163
164impl Serialize for MapValue {
165    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
166    where
167        S: serde::Serializer,
168    {
169        let mut s = serializer.serialize_struct("MapValue", 2)?;
170        s.serialize_field("value", &self.value)?;
171        s.serialize_field("lamport", &self.lamp)?;
172        s.serialize_field("id", &self.idlp())?;
173        s.end()
174    }
175}