mergable/
dict.rs

1/** A mergable dictionary.
2 *
3 * This dict must contain a `Mergable` value. This determines the semantics on conflict. For example if the value is a `Cell` then last-write-wins semantics will be used. However if the value is a `Bag` then multiple values inserted into the same key will be kept. If the value is a `Counter` than conflicting values will be summed.
4 */
5#[derive(Clone)]
6pub struct Dict<K, V, Seq> {
7	live: std::collections::HashMap<K, Value<V, Seq>>,
8
9	/** Removed entries.
10	 *
11	 * Keys are sequences of entires that have been deleted and values are when they were deleted.
12	 */
13	removed: std::collections::HashMap<Seq, Seq>,
14}
15
16pub struct DictDiff<K, V: crate::Mergable, Seq> {
17	updates: Vec<Update<K, V, Seq>>,
18}
19
20impl<
21	K,
22	V: crate::Mergable,
23	SF: crate::SequenceFactory,
24> crate::Diff
25for DictDiff<K, V, crate::Sequence<SF>> {
26	fn is_empty(&self) -> bool {
27		self.updates.is_empty()
28	}
29
30	fn revert(mut self) -> Result<Self, crate::RevertError> {
31		crate::map_in_place(&mut self.updates, |update| Ok(match update {
32			Update::Del(_what, Some((k, v)), when) => Update::Up(when.undo()?, k, UpdateValue::New(v)),
33			Update::Del(what, None, when) => Update::Del(what, None, when),
34			Update::Up(what, k, v) => match v {
35				UpdateValue::New(v) => {
36					Update::Del(what.clone(), Some((k, v)), what.undo()?)
37				}
38				UpdateValue::Diff(diff) => {
39					Update::Up(what, k, UpdateValue::Diff(crate::Diff::revert(diff)?))
40				},
41			}
42		}))?;
43		Ok(self)
44	}
45}
46
47impl<
48	K: Clone,
49	V: crate::Mergable + Clone,
50	Seq: Clone,
51>
52	Clone for DictDiff<K, V, Seq>
53where
54	V::Diff: Clone,
55{
56	fn clone(&self) -> Self {
57		DictDiff {
58			updates: self.updates.clone(),
59		}
60	}
61}
62
63impl<
64	K: std::fmt::Debug,
65	V: crate::Mergable + std::fmt::Debug,
66	Seq: std::fmt::Debug
67>
68	std::fmt::Debug for DictDiff<K, V, Seq>
69where V::Diff: std::fmt::Debug
70{
71	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
72		write!(f, "DictDiff(")?;
73		self.updates.fmt(f)?;
74		write!(f, ")")
75	}
76}
77
78#[derive(Clone,Debug)]
79enum UpdateValue<N, D> {
80	New(N),
81	Diff(D),
82}
83
84#[derive(Clone,Debug)]
85enum Update<K, V: crate::Mergable, Seq> {
86	Del(
87		/// What
88		Seq,
89		/// Value (for reverts)
90		Option<(K, V)>,
91		/// When
92		Seq,
93	),
94	Up(
95		/// What
96		Seq,
97		K,
98		UpdateValue<V, V::Diff>,
99	),
100}
101
102impl<
103	K: Clone + Eq + std::hash::Hash,
104	V: crate::Mergable,
105	SF: crate::SequenceFactory,
106>
107	Dict<K, V, crate::Sequence<SF>>
108{
109	pub fn entry(&mut self, key: K) -> DictEntry<K, V, SF> {
110		match self.live.entry(key) {
111			std::collections::hash_map::Entry::Occupied(entry) => {
112				DictEntry::Occupied(DictOccupiedEntry {
113					entry,
114					removed: &mut self.removed,
115				})
116			}
117			std::collections::hash_map::Entry::Vacant(entry) => {
118				DictEntry::Vacant(DictVacantEntry {
119					entry,
120				})
121			}
122		}
123	}
124
125	pub fn get<
126		Q: std::hash::Hash + Eq>
127		(&self, k: &Q) -> Option<&V>
128		where K: std::borrow::Borrow<Q>
129	{
130		self.live.get(k).map(|v| &v.value)
131	}
132
133	pub fn get_mut<
134		Q: std::hash::Hash + Eq>
135		(&mut self, k: &Q) -> Option<&mut V>
136		where K: std::borrow::Borrow<Q>
137	{
138		self.live.get_mut(k).map(|v| &mut v.value)
139	}
140
141	/** Insert a value into the map.
142	 *
143	 * Note that if the value is already in the map the two values will be *merged*. If you do not want this to occur `delete` the value first.
144
145	 * Also note that this updates the key's creation time meaning that deletes on the previous key will no longer be respected.
146
147	 * TODO: Weird revival stuff.
148	 */
149	pub fn insert(&mut self, ctx: &mut crate::Context<SF>, k: K, v: V) {
150		self.entry(k).insert(ctx, v);
151	}
152
153	/** Remove a value from the map.
154	 *
155	 * Note that the semantics of this operation can be confusing read the description carefully.
156	 *
157	 * This removes the *known* version of the element in the map and all older versions. Unknown modifications will not prevent deletion but if the element has been `insert`ed again after the version that we are aware of that insert will be preserved. Also note that due to merging semantics that may result in values from the known version "reappearing".
158	 */
159	pub fn remove<Q: ?Sized>(&mut self, ctx: &mut crate::Context<SF>, k: K) -> Option<V>
160		where
161			K: std::borrow::Borrow<Q>,
162			Q: std::hash::Hash + Eq
163	{
164		if let DictEntry::Occupied(entry) = self.entry(k) {
165			Some(entry.remove(ctx))
166		} else {
167			None
168		}
169	}
170
171	pub fn len(&self) -> usize {
172		self.live.len()
173	}
174
175	pub fn is_empty(&self) -> bool {
176		self.live.is_empty()
177	}
178
179	pub fn iter(&self) -> DictIter<K, V, crate::Sequence<SF>> {
180		return DictIter(self.live.iter());
181	}
182
183	fn apply(&mut self,
184		updates: impl IntoIterator<Item=Update<K, V, crate::Sequence<SF>>>,
185	) -> Result<(), crate::ApplyError> {
186		let mut unpurged_removals = std::collections::HashSet::new();
187		for update in updates {
188			match update {
189				Update::Del(what, value, when) => {
190					let removed_entry = match self.removed.entry(what) {
191						std::collections::hash_map::Entry::Occupied(mut entry) => {
192							if entry.get() < &when {
193								entry.insert(when.clone());
194							}
195							continue
196						}
197						std::collections::hash_map::Entry::Vacant(entry) => entry,
198					};
199
200					if let Some((k, _)) = value {
201						if let std::collections::hash_map::Entry::Occupied(entry) = self.live.entry(k) {
202							if entry.get().sequence == *removed_entry.key() {
203								eprintln!("remove");
204								entry.remove();
205							}
206						}
207					} else {
208						unpurged_removals.insert(removed_entry.key().clone());
209					}
210
211					removed_entry.insert(when.clone());
212				}
213				Update::Up(what, k, value) => {
214					match self.live.entry(k) {
215						std::collections::hash_map::Entry::Occupied(mut entry) => {
216							let slot = entry.get_mut();
217							if what > slot.sequence {
218								slot.sequence = what;
219							}
220							match value {
221								UpdateValue::Diff(d) => slot.value.apply(d)?,
222								UpdateValue::New(v) => slot.value.merge(v),
223							}
224						}
225						std::collections::hash_map::Entry::Vacant(entry) => {
226							if self.removed.contains_key(&what) {
227								continue
228							}
229
230							let UpdateValue::New(value) = value else {
231								return Err(crate::ApplyError::Missing(
232									"Target doesn't contain base value for diff.".into()))
233							};
234
235							entry.insert(Value{
236								sequence: what,
237								value,
238							});
239						}
240					}
241				}
242			}
243		}
244
245		if !unpurged_removals.is_empty() {
246			self.live.retain(|_, v| !unpurged_removals.contains(&v.sequence))
247		}
248
249		Ok(())
250	}
251}
252
253impl<
254	K: Clone + Eq + std::hash::Hash,
255	V: Clone + crate::Mergable<Seq=crate::Sequence<SF>>,
256	SF: crate::SequenceFactory,
257>
258	crate::Mergable for Dict<K, V, crate::Sequence<SF>>
259{
260	type Diff = DictDiff<K, V, crate::Sequence<SF>>;
261	type Seq = crate::Sequence<SF>;
262
263	fn merge(&mut self, that: Self) {
264		let removed = that.removed.into_iter()
265			.map(|(what, when)| Update::Del(what, None, when));
266		let live = that.live.into_iter()
267			.map(|(k, Value{sequence, value})| Update::Up(sequence, k, UpdateValue::New(value)));
268		self.apply(removed.chain(live)).unwrap()
269	}
270
271	fn diff(&self, that: &Self) -> Self::Diff {
272		let mut updates = Vec::<Update<K, V, crate::Sequence<SF>>>::new();
273
274		let mut deleted_seq = std::collections::HashMap::new();
275		for (what, when) in &self.removed {
276			if that.removed.get(what) >= Some(when) { continue }
277
278			let i = updates.len();
279			updates.push(Update::Del(what.clone(), None, when.clone()));
280			deleted_seq.insert(what, i);
281		}
282		if !deleted_seq.is_empty() {
283			for (k, v) in &that.live {
284				let Some(i) = deleted_seq.get(&v.sequence) else { continue };
285				let Update::Del(_, ref mut kv, _) = updates[*i] else { unreachable!() };
286				*kv = Some((k.clone(), v.value.clone()));
287			}
288		}
289
290		for (k, v) in &self.live {
291			if that.removed.contains_key(&v.sequence) { continue }
292			updates.push(
293				Update::Up(
294					v.sequence.clone(),
295					k.clone(),
296					match that.get(k) {
297						Some(known) => {
298							let diff = v.value.diff(known);
299							if crate::Diff::is_empty(&diff) { continue }
300							UpdateValue::Diff(diff)
301						}
302						None => UpdateValue::New(v.value.clone()),
303					}));
304		}
305
306		DictDiff { updates }
307	}
308
309	fn apply(&mut self, diff: Self::Diff) -> Result<(), crate::ApplyError> {
310		self.apply(diff.updates)
311	}
312
313	fn clean(&mut self, cutoff: &Self::Seq) {
314		for entry in self.live.values_mut() {
315			entry.value.clean(cutoff);
316		}
317		self.removed.retain(|_, seq| *seq >= *cutoff);
318	}
319}
320
321impl<
322	K,
323	V,
324	SF,
325>
326	Default for Dict<K, V, SF>
327{
328	fn default() -> Self {
329		Dict {
330			live: Default::default(),
331			removed: Default::default(),
332		}
333	}
334}
335
336impl<K: Eq + std::hash::Hash, V: PartialEq, Seq> PartialEq for Dict<K, V, Seq> {
337	fn eq(&self, that: &Self) -> bool {
338		self.live == that.live
339	}
340}
341
342impl<K: std::fmt::Debug, V: std::fmt::Debug, Seq> std::fmt::Debug for Dict<K, V, Seq> {
343	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
344		self.live.fmt(f)
345	}
346}
347
348#[derive(Clone)]
349struct Value<V, Seq> {
350	sequence: Seq,
351	value: V,
352}
353
354impl<V: PartialEq, Seq> PartialEq for Value<V, Seq> {
355	fn eq(&self, that: &Self) -> bool {
356		self.value == that.value
357	}
358}
359
360impl<V: std::fmt::Debug, Seq> std::fmt::Debug for Value<V, Seq> {
361	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
362		// write!(f, "{:?} @ {:?}", self.value, self.sequence)
363		self.value.fmt(f)
364	}
365}
366
367pub enum DictEntry<'a, K: 'a, V: 'a, SF: crate::SequenceFactory> {
368	Occupied(DictOccupiedEntry<'a, K, V, SF>),
369	Vacant(DictVacantEntry<'a, K, V, SF>),
370}
371
372impl<'a,
373	K: 'a + Eq + std::hash::Hash,
374	V: 'a + crate::Mergable,
375	SF: crate::SequenceFactory
376>
377	DictEntry<'a, K, V, SF>
378{
379	pub fn insert(self, ctx: &'a mut crate::Context<SF>, v: V) -> &'a mut V {
380		match self {
381			DictEntry::Occupied(mut entry) => {
382				entry.insert(ctx, v);
383				entry.into_mut()
384			}
385			DictEntry::Vacant(entry) => entry.insert(ctx, v),
386		}
387	}
388
389	pub fn or_insert(self, ctx: &'a mut crate::Context<SF>, v: V) -> &'a mut V {
390		match self {
391			DictEntry::Occupied(mut entry) => {
392				entry.insert(ctx, v);
393				entry.into_mut()
394			}
395			DictEntry::Vacant(entry) => entry.insert(ctx, v),
396		}
397	}
398}
399
400pub struct DictOccupiedEntry<'a, K: 'a, V: 'a, SF: crate::SequenceFactory> {
401	entry: std::collections::hash_map::OccupiedEntry<'a, K, Value<V, crate::Sequence<SF>>>,
402	removed: &'a mut std::collections::HashMap<crate::Sequence<SF>, crate::Sequence<SF>>,
403}
404
405impl<'a,
406	K: 'a + Eq + std::hash::Hash,
407	V: 'a + crate::Mergable,
408	SF: crate::SequenceFactory
409>
410	DictOccupiedEntry<'a, K, V, SF>
411{
412	pub fn into_mut(self) -> &'a mut V {
413		&mut self.entry.into_mut().value
414	}
415
416	pub fn insert(&mut self, ctx: &'a mut crate::Context<SF>, v: V) {
417		self.entry.get_mut().sequence = ctx.next_sequence();
418		self.entry.get_mut().value.merge(v);
419	}
420
421	pub fn remove(self, ctx: &'a mut crate::Context<SF>) -> V {
422		let (_, Value{sequence, value}) = self.entry.remove_entry();
423		self.removed.insert(sequence, ctx.next_sequence());
424		value
425	}
426}
427
428pub struct DictVacantEntry<'a, K: 'a, V: 'a, SF: crate::SequenceFactory> {
429	entry: std::collections::hash_map::VacantEntry<'a, K, Value<V, crate::Sequence<SF>>>,
430}
431
432impl<'a, K: 'a, V: 'a, SF: crate::SequenceFactory> DictVacantEntry<'a, K, V, SF> {
433	pub fn insert(self, ctx: &'a mut crate::Context<SF>, value: V) -> &'a mut V {
434		&mut self.entry.insert(
435			Value {
436				sequence: ctx.next_sequence(),
437				value,
438			})
439			.value
440	}
441}
442
443pub struct DictIter<'a, K, V, Seq>(std::collections::hash_map::Iter<'a, K, Value<V, Seq>>);
444
445impl<'a, K, V, Seq> Iterator for DictIter<'a, K, V, Seq> {
446	type Item = (&'a K, &'a V);
447
448	fn next(&mut self) -> Option<Self::Item> {
449		self.0.next()
450			.map(|item| (item.0, &item.1.value))
451	}
452}
453
454impl<
455	'a,
456	K: Clone + Eq + std::hash::Hash,
457	V: crate::Mergable,
458	SF: crate::SequenceFactory,
459> IntoIterator for &'a Dict<K, V, crate::Sequence<SF>> {
460	type IntoIter = DictIter<'a, K, V, crate::Sequence<SF>>;
461	type Item = (&'a K, &'a V);
462
463	fn into_iter(self) -> Self::IntoIter {
464		self.iter()
465	}
466}
467
468pub struct DictIntoIter<K, V, Seq>(std::collections::hash_map::IntoIter<K, Value<V, Seq>>);
469
470impl<K, V, Seq> Iterator for DictIntoIter<K, V, Seq> {
471	type Item = (K, V);
472
473	fn next(&mut self) -> Option<Self::Item> {
474		self.0.next()
475			.map(|item| (item.0, item.1.value))
476	}
477}
478
479impl<
480	K: Clone + Eq + std::hash::Hash,
481	V: crate::Mergable,
482	SF: crate::SequenceFactory,
483> IntoIterator for Dict<K, V, crate::Sequence<SF>> {
484	type IntoIter = DictIntoIter<K, V, crate::Sequence<SF>>;
485	type Item = (K, V);
486
487	fn into_iter(self) -> Self::IntoIter {
488		DictIntoIter(self.live.into_iter())
489	}
490}
491
492#[test]
493fn test_dict() {
494	let mut ctx = crate::Context::default();
495
496	let one = crate::Cell::new(&mut ctx, "one");
497	let two = crate::Cell::new(&mut ctx, "two");
498
499	let result = crate::test::test_merge(&mut [&one, &two]);
500	assert_eq!(*result, "two");
501
502	let mut parent_l = Dict::default();
503	parent_l.insert(&mut ctx, 0, two.clone());
504
505	let mut parent_r = Dict::default();
506	parent_r.insert(&mut ctx, 0, one.clone());
507
508	let merged = crate::test::test_merge(&mut [&parent_l, &parent_r]);
509	assert_eq!(merged, parent_l);
510
511	let mut child_l = merged.clone();
512	child_l.insert(&mut ctx, 1, one.clone());
513
514	let mut child_r = merged;
515	child_r.insert(&mut ctx, 2, two.clone());
516
517	let merged = crate::test::test_merge(&mut [&parent_l, &parent_r, &child_l, &child_r]);
518	let mut expected = Dict::default();
519	expected.insert(&mut ctx, 0, two.clone());
520	expected.insert(&mut ctx, 1, one.clone());
521	expected.insert(&mut ctx, 2, two.clone());
522	assert_eq!(merged, expected);
523}
524
525#[test]
526fn test_dict_remove_old() {
527	let mut ctx = crate::Context::default();
528
529	let one = crate::Cell::new(&mut ctx, "one");
530	let two = crate::Cell::new(&mut ctx, "two");
531
532	let mut parent_l = Dict::default();
533	parent_l.insert(&mut ctx, 0, two.clone());
534
535	let mut parent_r = Dict::default();
536	parent_r.insert(&mut ctx, 0, one.clone());
537
538	// We remove the left entry. However the right is created after this.
539	parent_l.remove(&mut ctx, 0);
540
541	let merged = crate::test::test_merge(&mut [&parent_l, &parent_r]);
542	assert_eq!(merged, parent_r);
543}
544
545#[test]
546fn test_dict_remove_new() {
547	let mut ctx = crate::Context::default();
548
549	let one = crate::Cell::new(&mut ctx, "one");
550	let two = crate::Cell::new(&mut ctx, "two");
551
552	let mut parent_l = Dict::default();
553	parent_l.insert(&mut ctx, 0, two.clone());
554
555	let mut parent_r = Dict::default();
556	parent_r.insert(&mut ctx, 0, one.clone());
557
558	// We remove the right entry. Since this was created later the removal wins.
559	parent_r.remove(&mut ctx, 0);
560
561	let merged = crate::test::test_merge(&mut [&parent_l, &parent_r]);
562	assert_eq!(merged, parent_l);
563}
564
565#[test]
566fn test_dict_remove_merge_revive() {
567	let mut ctx = crate::Context::default();
568
569	let one = crate::Cell::new(&mut ctx, "one");
570	let two = crate::Cell::new(&mut ctx, "two");
571
572	let mut root = Dict::default();
573	root.insert(&mut ctx, 0, two.clone());
574
575	// Note that this "insert" actually merges the cells, resulting in "two" winning because it is newer (even though the insert happened earlier.
576	let mut child_insert = root.clone();
577	child_insert.insert(&mut ctx, 0, one.clone());
578
579	// This removes the value. However since it doesn't know about child_insert's insertion that is preserved and the "two" value is "revived".
580	let mut child_remove = root.clone();
581	child_remove.remove(&mut ctx, 0);
582
583	let merged = crate::test::test_merge(&mut [&child_remove, &child_insert]);
584	assert_eq!(merged, child_insert);
585}
586
587#[test]
588fn test_undo_insert() {
589	let mut ctx = crate::Context::default();
590
591	let mut base = Dict::default();
592
593	let v = crate::Cell::new(&mut ctx, "one");
594	base.insert(&mut ctx, 1, v);
595
596	let mut updated = base.clone();
597
598	let v = crate::Cell::new(&mut ctx, "two");
599	updated.insert(&mut ctx, 2, v);
600	let diff_two = crate::Mergable::diff(&updated, &base);
601	crate::Mergable::apply(&mut base, diff_two.clone()).unwrap();
602
603	let initial = updated.clone();
604
605	let v = crate::Cell::new(&mut ctx, "three");
606	updated.insert(&mut ctx, 3, v);
607	let diff_three = crate::Mergable::diff(&updated, &base);
608
609	let revert = crate::Diff::revert(diff_two).unwrap();
610
611	let result = crate::test::test_apply(initial, &mut [
612		diff_three,
613		revert,
614	]);
615
616	updated.remove(&mut ctx, 2);
617	assert_eq!(result, updated);
618}
619
620#[test]
621fn test_undo_remove() {
622	let mut ctx = crate::Context::default();
623
624	let mut base = Dict::default();
625
626	let v = crate::Cell::new(&mut ctx, "one");
627	base.insert(&mut ctx, 1, v);
628	let v = crate::Cell::new(&mut ctx, "two");
629	base.insert(&mut ctx, 2, v);
630
631	let mut updated = base.clone();
632
633	updated.remove(&mut ctx, 2);
634	let diff_two_remove = crate::Mergable::diff(&updated, &base);
635	crate::Mergable::apply(&mut base, diff_two_remove.clone()).unwrap();
636
637	let initial = base.clone();
638
639	let v = crate::Cell::new(&mut ctx, "three");
640	updated.insert(&mut ctx, 3, v);
641	let diff_three = crate::Mergable::diff(&updated, &base);
642
643	let revert = crate::Diff::revert(diff_two_remove.clone()).unwrap();
644
645	let result = crate::test::test_apply(initial, &mut [
646		diff_three,
647		revert,
648	]);
649
650	let mut expected = Dict::default();
651	let v = crate::Cell::new(&mut ctx, "one");
652	expected.insert(&mut ctx, 1, v);
653	let v = crate::Cell::new(&mut ctx, "two");
654	expected.insert(&mut ctx, 2, v);
655	let v = crate::Cell::new(&mut ctx, "three");
656	expected.insert(&mut ctx, 3, v);
657	assert_eq!(result, expected);
658}
659
660#[test]
661fn test_undo_update() {
662	let mut ctx = crate::Context::default();
663
664	let mut base = Dict::default();
665
666	let mut sub = Dict::default();
667	let v = crate::Cell::new(&mut ctx, "one");
668	sub.insert(&mut ctx, 1, v);
669
670	base.insert(&mut ctx, (), sub);
671
672	let mut updated = base.clone();
673
674	let v = crate::Cell::new(&mut ctx, "two");
675	updated.get_mut(&()).unwrap().insert(&mut ctx, 2, v);
676
677	let diff_two = crate::Mergable::diff(&updated, &base);
678	let revert_diff_two = crate::Diff::revert(diff_two.clone()).unwrap();
679	dbg!(&updated, &base, &diff_two, &revert_diff_two);
680	crate::Mergable::apply(&mut base, diff_two).unwrap();
681
682	let v = crate::Cell::new(&mut ctx, "three");
683	updated.get_mut(&()).unwrap().insert(&mut ctx, 3, v);
684	let diff_three = crate::Mergable::diff(&updated, &base);
685
686	let result = crate::test::test_apply(base, &mut [
687		diff_three,
688		revert_diff_two,
689	]);
690
691	let mut sub = Dict::default();
692	let v = crate::Cell::new(&mut ctx, "one");
693	sub.insert(&mut ctx, 1, v);
694	let v = crate::Cell::new(&mut ctx, "three");
695	sub.insert(&mut ctx, 3, v);
696	let mut expected = Dict::default();
697	expected.insert(&mut ctx, (), sub);
698	assert_eq!(result, expected);
699}
700
701#[test]
702fn test_undo_old_update() {
703	let mut ctx = crate::Context::default();
704
705	let mut base = Dict::default();
706
707	let mut sub = Dict::default();
708	let v = crate::Cell::new(&mut ctx, "one");
709	sub.insert(&mut ctx, 1, v);
710
711	base.insert(&mut ctx, (), sub);
712
713	let mut updated = base.clone();
714
715	let v = crate::Cell::new(&mut ctx, "two");
716	updated.get_mut(&()).unwrap().insert(&mut ctx, 2, v);
717
718	let diff_two = crate::Mergable::diff(&updated, &base);
719	let revert_diff_two = crate::Diff::revert(diff_two.clone()).unwrap();
720	crate::Mergable::apply(&mut base, diff_two).unwrap();
721
722	let v = crate::Cell::new(&mut ctx, "three");
723	updated.get_mut(&()).unwrap().insert(&mut ctx, 3, v);
724	let diff_three = crate::Mergable::diff(&updated, &base);
725
726	let result = crate::test::test_apply(base, &mut [
727		diff_three,
728		revert_diff_two,
729	]);
730
731	let mut sub = Dict::default();
732	let v = crate::Cell::new(&mut ctx, "one");
733	sub.insert(&mut ctx, 1, v);
734	let v = crate::Cell::new(&mut ctx, "three");
735	sub.insert(&mut ctx, 3, v);
736	let mut expected = Dict::default();
737	expected.insert(&mut ctx, (), sub);
738	assert_eq!(result, expected);
739}
740
741#[test]
742fn test_iter() {
743	let mut ctx = crate::Context::default();
744
745	let one = crate::Cell::new(&mut ctx, "one");
746	let two = crate::Cell::new(&mut ctx, "two");
747	let three = crate::Cell::new(&mut ctx, "three");
748
749	let mut dict = Dict::default();
750	dict.insert(&mut ctx, 1, one);
751	dict.insert(&mut ctx, 2, two);
752	dict.remove(&mut ctx, 2);
753	dict.insert(&mut ctx, 3, three);
754
755	let mut seen = Vec::with_capacity(2);
756	for (k, v) in &dict {
757		seen.push((*k, **v));
758	}
759	seen.sort_unstable();
760	assert_eq!(seen, &[(1, "one"), (3, "three")]);
761}
762
763#[test]
764fn test_into_iter() {
765	let mut ctx = crate::Context::default();
766
767	let one = crate::Cell::new(&mut ctx, "one".to_string());
768	let two = crate::Cell::new(&mut ctx, "two".to_string());
769	let three = crate::Cell::new(&mut ctx, "three".to_string());
770
771	let mut dict = Dict::default();
772	dict.insert(&mut ctx, "1".to_string(), one);
773	dict.insert(&mut ctx, "2".to_string(), two);
774	dict.remove::<String>(&mut ctx, "2".to_string());
775	dict.insert(&mut ctx, "3".to_string(), three);
776
777	let mut seen = Vec::with_capacity(2);
778	for (k, v) in dict {
779		seen.push((k, v.into()));
780	}
781	seen.sort_unstable();
782	assert_eq!(seen, &[
783		("1".to_string(), "one".to_string()),
784		("3".to_string(), "three".to_string()),
785	]);
786}
787
788#[test]
789fn test_clean() {
790	let mut ctx = crate::Context::default();
791
792	let mut d1 = Dict::default();
793	let one = crate::Cell::new(&mut ctx, "one");
794	d1.insert(&mut ctx, 1, one);
795
796	let d2 = d1.clone();
797
798	let seq_fork = ctx.next_sequence();
799
800	d1.remove(&mut ctx, 1);
801
802	let seq_remove = ctx.next_sequence();
803
804	assert_eq!(d1.removed.len(), 1);
805	crate::Mergable::clean(&mut d1, &seq_fork);
806	// Nothing was removed at this point.
807	assert_eq!(d1.removed.len(), 1);
808
809	// The remove is remembered because it happened last.
810	let result = crate::test::test_merge(&mut [&d1, &d2]);
811	assert_eq!(result.len(), 0);
812
813	crate::Mergable::clean(&mut d1, &seq_remove);
814	// All deletions happened before the cutoff.
815	assert_eq!(d1.removed.len(), 0);
816
817	// Merging with d2 with values before the cutoff causes unintended revival.
818	let result = crate::test::test_merge(&mut [&d1, &d2]);
819	assert_eq!(result.len(), 1);
820}