Skip to main content

automerge/iter/
map_range.rs

1use super::tools::{Diff, DiffIter, ExIdPromise, Shiftable, Unshift};
2use crate::clock::{Clock, ClockRange};
3use crate::exid::ExId;
4use crate::op_set2::op_set::{ActionIter, OpIdIter, OpSet, ValueIter};
5use crate::op_set2::types::{Action, ScalarValue, ValueRef};
6use crate::patches::PatchLog;
7use crate::types::{ObjId, OpId, TextEncoding};
8
9use hexane::{ColumnDataIter, StrCursor};
10
11use std::borrow::Cow;
12use std::fmt::Debug;
13use std::ops::Range;
14
15#[derive(Debug, Clone, PartialEq)]
16pub struct MapRangeItem<'a> {
17    pub key: Cow<'a, str>,
18    pub value: ValueRef<'a>,
19    pub conflict: bool,
20    pub(crate) pos: usize,
21    pub(crate) maybe_exid: ExIdPromise<'a>,
22}
23
24impl MapRangeItem<'_> {
25    pub(crate) fn op_id(&self) -> OpId {
26        self.maybe_exid.id
27    }
28
29    pub fn id(&self) -> ExId {
30        self.maybe_exid.exid()
31    }
32
33    pub fn into_owned(self) -> MapRangeItem<'static> {
34        MapRangeItem {
35            key: Cow::Owned(self.key.into_owned()),
36            value: self.value.into_owned(),
37            conflict: self.conflict,
38            pos: self.pos,
39            maybe_exid: self.maybe_exid.into_owned(),
40        }
41    }
42}
43
44#[derive(Debug, Clone, PartialEq)]
45pub(crate) struct MapDiffItem<'a> {
46    pub(crate) diff: Diff,
47    pub(crate) key: Cow<'a, str>,
48    pub(crate) value: ValueRef<'a>,
49    pub(crate) inc: i64,
50    pub(crate) conflict: bool,
51    pub(crate) expose: bool,
52    pub(crate) pos: usize,
53    pub(crate) id: OpId,
54}
55
56impl<'a> MapDiffItem<'a> {
57    pub(crate) fn export(self, op_set: &'a OpSet) -> MapRangeItem<'a> {
58        let maybe_exid = ExIdPromise::new(op_set, self.id);
59        MapRangeItem {
60            key: self.key,
61            value: self.value,
62            conflict: self.conflict,
63            pos: self.pos,
64            maybe_exid,
65        }
66    }
67    fn update(&mut self, expose: bool) {
68        self.expose |= expose;
69        if self.expose && self.diff == Diff::Same {
70            self.diff = Diff::Add;
71        }
72    }
73
74    pub(crate) fn log(self, obj: ObjId, log: &mut PatchLog, encoding: TextEncoding) {
75        match self.diff {
76            Diff::Add => log.put_map(
77                obj,
78                &self.key,
79                self.value.hydrate(encoding),
80                self.id,
81                self.conflict,
82                self.expose,
83            ),
84            Diff::Same => {
85                if self.inc != 0 {
86                    log.increment_map(obj, &self.key, self.inc, self.id);
87                } else if self.conflict {
88                    log.flag_conflict_map(obj, &self.key);
89                }
90            }
91            Diff::Del => log.delete_map(obj, &self.key),
92        }
93    }
94}
95
96#[derive(Debug, Clone, Default)]
97pub struct MapRange<'a> {
98    iter: MapDiff<'a>,
99}
100
101impl<'a> Iterator for MapRange<'a> {
102    type Item = MapRangeItem<'a>;
103
104    fn next(&mut self) -> Option<Self::Item> {
105        Some(self.iter.next()?.export(self.iter.op_set?))
106    }
107}
108
109#[derive(Clone, Default, Debug)]
110struct MapIter<'a> {
111    id: OpIdIter<'a>,
112    key_str: ColumnDataIter<'a, StrCursor>,
113    action: ActionIter<'a>,
114    value: ValueIter<'a>,
115}
116
117impl Shiftable for MapIter<'_> {
118    fn shift_next(&mut self, range: Range<usize>) -> Option<<Self as Iterator>::Item> {
119        let id = self.id.shift_next(range.clone());
120        let key = self.key_str.shift_next(range.clone());
121        let action = self.action.shift_next(range.clone());
122        let value = self.value.shift_next(range);
123        let pos = self.id.pos() - 1;
124        Some(MapEntry {
125            key: key??,
126            action: action?,
127            value: value?,
128            id: id?,
129            pos,
130        })
131    }
132}
133
134#[derive(Clone, Debug)]
135struct MapEntry<'a> {
136    id: OpId,
137    pos: usize,
138    key: Cow<'a, str>,
139    action: Action,
140    value: ScalarValue<'a>,
141}
142
143impl<'a> MapEntry<'a> {
144    fn diff_item(
145        self,
146        value: ValueRef<'a>,
147        inc: i64,
148        mut diff: Diff,
149        conflict: bool,
150        expose: bool,
151    ) -> MapDiffItem<'a> {
152        let key = self.key;
153        let pos = self.pos;
154        let id = self.id;
155        if expose && diff == Diff::Same {
156            diff = Diff::Add;
157        }
158        MapDiffItem {
159            diff,
160            key,
161            value,
162            inc,
163            conflict,
164            expose,
165            id,
166            pos,
167        }
168    }
169}
170
171impl<'a> Iterator for MapIter<'a> {
172    type Item = MapEntry<'a>;
173
174    fn next(&mut self) -> Option<Self::Item> {
175        let id = self.id.next()?;
176        let key = self.key_str.next()??;
177        let action = self.action.next()?;
178        let value = self.value.next()?;
179        let pos = self.id.pos() - 1;
180        Some(MapEntry {
181            id,
182            pos,
183            key,
184            action,
185            value,
186        })
187    }
188
189    fn nth(&mut self, n: usize) -> Option<Self::Item> {
190        let id = self.id.nth(n)?;
191        let key = self.key_str.nth(n)??;
192        let action = self.action.nth(n)?;
193        let value = self.value.nth(n)?;
194        let pos = self.id.pos() - 1;
195        Some(MapEntry {
196            key,
197            action,
198            value,
199            id,
200            pos,
201        })
202    }
203}
204
205impl<'a> MapRange<'a> {
206    pub(crate) fn new(op_set: &'a OpSet, range: Range<usize>, clock: Option<Clock>) -> Self {
207        let iter = MapDiff::new(op_set, range, ClockRange::current(clock));
208        Self { iter }
209    }
210
211    pub(crate) fn shift_next(&mut self, range: Range<usize>) -> Option<<Self as Iterator>::Item> {
212        self.iter.iter.shift(range);
213        self.next()
214    }
215}
216
217#[derive(Debug, Clone, Default)]
218pub(crate) struct MapDiff<'a> {
219    op_set: Option<&'a OpSet>,
220    iter: Unshift<DiffIter<'a, MapIter<'a>>>,
221    clock: ClockRange,
222}
223
224impl<'a> Iterator for MapDiff<'a> {
225    type Item = MapDiffItem<'a>;
226
227    fn next(&mut self) -> Option<Self::Item> {
228        let op_set = self.op_set.as_mut()?;
229        let mut last_is_same = false;
230        let mut num_new = 0;
231        let mut num_old = 0;
232        let mut expose;
233        let mut last_visible: Option<Self::Item> = None;
234
235        while let Some((diff, map)) = self.iter.next() {
236            match diff {
237                Diff::Del => {
238                    expose = last_is_same;
239                    num_old += 1;
240                }
241                Diff::Same => {
242                    last_is_same = true;
243                    num_new += 1;
244                    num_old += 1;
245                    expose = false;
246                }
247                Diff::Add => {
248                    last_is_same = false;
249                    num_new += 1;
250                    expose = self.clock.predates(&map.id);
251                }
252            }
253            let value;
254            let inc;
255            if let ScalarValue::Counter(c) = &map.value {
256                let (inc1, inc2) = op_set.get_increment_diff_at_pos(map.pos, &self.clock);
257                inc = inc2 - inc1;
258                value = ValueRef::from_action_value(map.action, ScalarValue::Counter(*c + inc2));
259            } else {
260                value = ValueRef::from_action_value(map.action, map.value.clone());
261                inc = 0;
262            }
263
264            let old_conflict = diff == Diff::Same && num_old > 1;
265            let conflict = num_new > 1 && !old_conflict;
266
267            if let Some((next_diff, next_map)) = self.iter.peek() {
268                if next_map.key == map.key {
269                    if diff.is_visible() && next_diff.is_del() {
270                        last_visible = Some(map.diff_item(value, inc, diff, conflict, expose));
271                    }
272                    continue;
273                }
274            }
275
276            if diff.is_del() {
277                if let Some(mut last) = last_visible.take() {
278                    last.update(expose);
279                    return Some(last);
280                }
281            }
282            return Some(map.diff_item(value, inc, diff, conflict, expose));
283        }
284        None
285    }
286}
287
288impl<'a> MapDiff<'a> {
289    pub(crate) fn new(op_set: &'a OpSet, range: Range<usize>, clock: ClockRange) -> Self {
290        let key_str = op_set.key_str_iter_range(&range);
291        let action = op_set.action_iter_range(&range);
292        let value = op_set.value_iter_range(&range);
293        let id = op_set.id_iter_range(&range);
294
295        let map_iter = MapIter {
296            id,
297            key_str,
298            value,
299            action,
300        };
301
302        let skip = DiffIter::new(op_set, map_iter, clock.clone(), range);
303        let iter = Unshift::new(skip);
304
305        Self {
306            op_set: Some(op_set),
307            iter,
308            clock,
309        }
310    }
311
312    pub(crate) fn shift_next(&mut self, range: Range<usize>) -> Option<<Self as Iterator>::Item> {
313        self.iter.shift(range);
314        self.next()
315    }
316}