Skip to main content

mergable/
cell.rs

1pub struct Cell<T, Seq> {
2	sequence: Seq,
3	value: T,
4}
5
6impl<T, SequenceFactory: crate::SequenceFactory> Cell<T, crate::Sequence<SequenceFactory>> {
7	pub fn new(ctx: &mut crate::Context<SequenceFactory>, value: T) -> Self {
8		Cell {
9			sequence: ctx.next_sequence(),
10			value,
11		}
12	}
13
14	pub fn set(&mut self, ctx: &mut crate::Context<SequenceFactory>, value: T) {
15		*self.borrow_mut(ctx) = value;
16	}
17
18	pub fn last_modified(&self) -> &crate::Sequence<SequenceFactory> {
19		&self.sequence
20	}
21
22	/** Mutably borrow the cell.
23	 *
24	 * Note that the following lines are equivalent. The benefit of `borrow_mut()` is for values that are not (cheaply) clonable.
25	 *
26	 * ```
27	 * # let mut ctx = mergable::Context::default();
28	 * # let mut cell = mergable::Cell::new(&mut ctx, 0);
29	 * *cell.borrow_mut(&mut ctx) += 1;
30	 * cell.set(&mut ctx, *cell.clone() + 1);
31	 * ```
32	 */
33	pub fn borrow_mut(&mut self, ctx: &mut crate::Context<SequenceFactory>) -> &mut T {
34		self.sequence = ctx.next_sequence();
35		&mut self.value
36	}
37
38	pub fn into(self) -> T {
39		self.value
40	}
41}
42
43#[derive(Clone,Debug)]
44pub struct CellDiff<T, Seq>(Option<Update<T, Seq>>);
45
46#[derive(Clone,Debug)]
47struct Update<T, Seq> {
48	new: Cell<T, Seq>,
49	old: T,
50}
51
52impl<
53	T: Clone,
54	SequenceFactory: crate::SequenceFactory,
55> crate::Mergable
56for Cell<T, crate::Sequence<SequenceFactory>> {
57	type Diff = CellDiff<T, crate::Sequence<SequenceFactory>>;
58	type Seq = crate::Sequence<SequenceFactory>;
59
60	fn merge(&mut self, other: Self) {
61		if other.sequence > self.sequence {
62			*self = other
63		}
64
65		// TODO: If the sequences are equal the values *must* be identical. It would be nice to add an assert but I don't want to force `T: PartialEq`.
66	}
67
68	fn diff(&self, other: &Self) -> Self::Diff {
69		CellDiff(if self.sequence > other.sequence {
70			Some(Update{
71				new: self.clone(),
72				old: other.value.clone(),
73			})
74		} else {
75			None
76		})
77	}
78
79	fn apply(&mut self, diff: Self::Diff) -> Result<(), crate::ApplyError> {
80		if let Some(diff) = diff.0 {
81			self.merge(diff.new);
82		}
83
84		Ok(())
85	}
86
87	fn clean(&mut self, _cutoff: &Self::Seq) {
88		// Cell doesn't keep history.
89
90		// TODO: It would be nice if we could propagate `clean()` to our child if it is Mergable. This could form some sort of "resettable" container. However that requires specialization
91		// https://github.com/rust-lang/rust/issues/31844
92	}
93}
94
95
96impl<T, SequenceFactory: crate::SequenceFactory> crate::Diff
97for CellDiff<T, crate::Sequence<SequenceFactory>> {
98	fn is_empty(&self) -> bool {
99		self.0.is_none()
100	}
101
102	fn revert(mut self) -> Result<Self, crate::RevertError> {
103		if let Some(ref mut diff) = self.0 {
104			diff.new.sequence = diff.new.sequence.undo()?;
105			std::mem::swap(&mut diff.new.value, &mut diff.old);
106		}
107		Ok(self)
108	}
109}
110
111impl<T: Clone, SF: Clone> Clone for Cell<T, SF> {
112	fn clone(&self) -> Self {
113		Cell {
114			sequence: self.sequence.clone(),
115			value: self.value.clone(),
116		}
117	}
118}
119
120impl<T, SF> std::ops::Deref for Cell<T, SF> {
121	type Target = T;
122
123	fn deref(&self) -> &T {
124		&self.value
125	}
126}
127
128impl<T: PartialEq, Seq> PartialEq for Cell<T, Seq> {
129	fn eq(&self, other: &Self) -> bool {
130		self.value == other.value
131	}
132}
133
134impl<T: std::fmt::Debug, Seq> std::fmt::Debug for Cell<T, Seq> {
135	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
136		self.value.fmt(f)
137	}
138}
139
140#[test]
141fn test_merge() {
142	let mut ctx = crate::Context::default();
143
144	let result = crate::test::test_merge(&mut [
145		&Cell::new(&mut ctx, "one"),
146		&Cell::new(&mut ctx, "two"),
147		&Cell::new(&mut ctx, "six"),
148	]);
149	assert_eq!(result.value, "six");
150}
151
152#[test]
153fn test_update() {
154	let mut ctx = crate::Context::default();
155
156	let initial = Cell::new(&mut ctx, "old");
157	let mut update = initial.clone();
158	update.set(&mut ctx, "new");
159
160	let result = crate::test::test_merge(&mut [&initial, &update]);
161	assert_eq!(result.value, "new");
162}
163
164#[test]
165fn test_revert() {
166	let mut ctx = crate::Context::default();
167
168	let initial = Cell::new(&mut ctx, "old");
169	let mut update = initial.clone();
170	update.set(&mut ctx, "new");
171
172	let diff = crate::Mergable::diff(&update, &initial);
173	let revert = crate::Diff::revert(diff).unwrap();
174	crate::Mergable::apply(&mut update, revert).unwrap();
175
176	assert_eq!(update.value, "old");
177}
178
179#[test]
180fn test_revert_stale() {
181	let mut ctx = crate::Context::default();
182
183	let orig = Cell::new(&mut ctx, "old");
184
185	let mut base = orig.clone();
186
187	let mut updated = base.clone();
188	updated.set(&mut ctx, "new");
189
190	let diff_new = crate::Mergable::diff(&updated, &base);
191	crate::Mergable::apply(&mut base, diff_new.clone()).unwrap();
192
193	updated.set(&mut ctx, "newer");
194
195	let diff_newer = crate::Mergable::diff(&updated, &base);
196	crate::Mergable::apply(&mut base, diff_newer.clone()).unwrap();
197
198	let revert = crate::Diff::revert(diff_new.clone()).unwrap();
199
200	let result = crate::test::test_apply(orig, &mut [
201		diff_new,
202		diff_newer,
203		revert,
204	]);
205
206	assert_eq!(result.value, "newer");
207}