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}