pwasm_utils/
ref_list.rs

1#![warn(missing_docs)]
2
3use crate::std::{cell::RefCell, rc::Rc, slice, vec::Vec};
4
5#[derive(Debug)]
6enum EntryOrigin {
7	Index(usize),
8	Detached,
9}
10
11impl From<usize> for EntryOrigin {
12	fn from(v: usize) -> Self {
13		EntryOrigin::Index(v)
14	}
15}
16
17/// Reference counting, link-handling object.
18#[derive(Debug)]
19pub struct Entry<T> {
20	val: T,
21	index: EntryOrigin,
22}
23
24impl<T> Entry<T> {
25	/// New entity.
26	pub fn new(val: T, index: usize) -> Entry<T> {
27		Entry { val, index: EntryOrigin::Index(index) }
28	}
29
30	/// New detached entry.
31	pub fn new_detached(val: T) -> Entry<T> {
32		Entry { val, index: EntryOrigin::Detached }
33	}
34
35	/// Index of the element within the reference list.
36	pub fn order(&self) -> Option<usize> {
37		match self.index {
38			EntryOrigin::Detached => None,
39			EntryOrigin::Index(idx) => Some(idx),
40		}
41	}
42}
43
44impl<T> crate::std::ops::Deref for Entry<T> {
45	type Target = T;
46
47	fn deref(&self) -> &T {
48		&self.val
49	}
50}
51
52impl<T> crate::std::ops::DerefMut for Entry<T> {
53	fn deref_mut(&mut self) -> &mut T {
54		&mut self.val
55	}
56}
57
58/// Reference to the entry in the rerence list.
59#[derive(Debug)]
60pub struct EntryRef<T>(Rc<RefCell<Entry<T>>>);
61
62impl<T> Clone for EntryRef<T> {
63	fn clone(&self) -> Self {
64		EntryRef(self.0.clone())
65	}
66}
67
68impl<T> From<Entry<T>> for EntryRef<T> {
69	fn from(v: Entry<T>) -> Self {
70		EntryRef(Rc::new(RefCell::new(v)))
71	}
72}
73
74impl<T> EntryRef<T> {
75	/// Read the reference data.
76	pub fn read(&self) -> crate::std::cell::Ref<Entry<T>> {
77		self.0.borrow()
78	}
79
80	/// Try to modify internal content of the referenced object.
81	///
82	/// May panic if it is already borrowed.
83	pub fn write(&self) -> crate::std::cell::RefMut<Entry<T>> {
84		self.0.borrow_mut()
85	}
86
87	/// Index of the element within the reference list.
88	pub fn order(&self) -> Option<usize> {
89		self.0.borrow().order()
90	}
91
92	/// Number of active links to this entity.
93	pub fn link_count(&self) -> usize {
94		Rc::strong_count(&self.0) - 1
95	}
96}
97
98/// List that tracks references and indices.
99#[derive(Debug)]
100pub struct RefList<T> {
101	items: Vec<EntryRef<T>>,
102}
103
104impl<T> Default for RefList<T> {
105	fn default() -> Self {
106		RefList { items: Default::default() }
107	}
108}
109
110impl<T> RefList<T> {
111	/// New empty list.
112	pub fn new() -> Self {
113		Self::default()
114	}
115
116	/// Push new element in the list.
117	///
118	/// Returns refernce tracking entry.
119	pub fn push(&mut self, t: T) -> EntryRef<T> {
120		let idx = self.items.len();
121		let val: EntryRef<_> = Entry::new(t, idx).into();
122		self.items.push(val.clone());
123		val
124	}
125
126	/// Start deleting.
127	///
128	/// Start deleting some entries in the list. Returns transaction
129	/// that can be populated with number of removed entries.
130	/// When transaction is finailized, all entries are deleted and
131	/// internal indices of other entries are updated.
132	pub fn begin_delete(&mut self) -> DeleteTransaction<T> {
133		DeleteTransaction { list: self, deleted: Vec::new() }
134	}
135
136	/// Start inserting.
137	///
138	/// Start inserting some entries in the list at he designated position.
139	/// Returns transaction that can be populated with some entries.
140	/// When transaction is finailized, all entries are inserted and
141	/// internal indices of other entries might be updated.
142	pub fn begin_insert(&mut self, at: usize) -> InsertTransaction<T> {
143		InsertTransaction { at, list: self, items: Vec::new() }
144	}
145
146	/// Start inserting after the condition first matches (or at the end).
147	///
148	/// Start inserting some entries in the list at he designated position.
149	/// Returns transaction that can be populated with some entries.
150	/// When transaction is finailized, all entries are inserted and
151	/// internal indices of other entries might be updated.
152	pub fn begin_insert_after<F>(&mut self, mut f: F) -> InsertTransaction<T>
153	where
154		F: FnMut(&T) -> bool,
155	{
156		let pos = self
157			.items
158			.iter()
159			.position(|rf| f(&**rf.read()))
160			.map(|x| x + 1)
161			.unwrap_or(self.items.len());
162
163		self.begin_insert(pos)
164	}
165
166	/// Start inserting after the condition first no longer true (or at the end).
167	///
168	/// Start inserting some entries in the list at he designated position.
169	/// Returns transaction that can be populated with some entries.
170	/// When transaction is finailized, all entries are inserted and
171	/// internal indices of other entries might be updated.
172	pub fn begin_insert_not_until<F>(&mut self, mut f: F) -> InsertTransaction<T>
173	where
174		F: FnMut(&T) -> bool,
175	{
176		let pos = self.items.iter().take_while(|rf| f(&**rf.read())).count();
177		self.begin_insert(pos)
178	}
179
180	/// Get entry with index (checked).
181	///
182	/// Can return None when index out of bounts.
183	pub fn get(&self, idx: usize) -> Option<EntryRef<T>> {
184		self.items.get(idx).cloned()
185	}
186
187	fn done_delete(&mut self, indices: &[usize]) {
188		for entry in self.items.iter_mut() {
189			let mut entry = entry.write();
190			let total_less = indices
191				.iter()
192				.take_while(|x| {
193					**x < entry.order().expect("Items in the list always have order; qed")
194				})
195				.count();
196			match &mut entry.index {
197				EntryOrigin::Detached => unreachable!("Items in the list always have order!"),
198				EntryOrigin::Index(idx) => {
199					*idx -= total_less;
200				},
201			};
202		}
203
204		for (total_removed, idx) in indices.iter().enumerate() {
205			let detached = self.items.remove(*idx - total_removed);
206			detached.write().index = EntryOrigin::Detached;
207		}
208	}
209
210	fn done_insert(&mut self, index: usize, mut items: Vec<EntryRef<T>>) {
211		let mut offset = 0;
212		for item in items.drain(..) {
213			item.write().index = EntryOrigin::Index(index + offset);
214			self.items.insert(index + offset, item);
215			offset += 1;
216		}
217
218		for idx in (index + offset)..self.items.len() {
219			self.get_ref(idx).write().index = EntryOrigin::Index(idx);
220		}
221	}
222
223	/// Delete several items.
224	pub fn delete(&mut self, indices: &[usize]) {
225		self.done_delete(indices)
226	}
227
228	/// Delete one item.
229	pub fn delete_one(&mut self, index: usize) {
230		self.done_delete(&[index])
231	}
232
233	/// Initialize from slice.
234	///
235	/// Slice members are cloned.
236	pub fn from_slice(list: &[T]) -> Self
237	where
238		T: Clone,
239	{
240		let mut res = Self::new();
241
242		for t in list {
243			res.push(t.clone());
244		}
245
246		res
247	}
248
249	/// Length of the list.
250	pub fn len(&self) -> usize {
251		self.items.len()
252	}
253
254	/// Returns true iff len == 0.
255	pub fn is_empty(&self) -> bool {
256		self.len() == 0
257	}
258
259	/// Clone entry (reference counting object to item) by index.
260	///
261	/// Will panic if index out of bounds.
262	pub fn clone_ref(&self, idx: usize) -> EntryRef<T> {
263		self.items[idx].clone()
264	}
265
266	/// Get reference to entry by index.
267	///
268	/// Will panic if index out of bounds.
269	pub fn get_ref(&self, idx: usize) -> &EntryRef<T> {
270		&self.items[idx]
271	}
272
273	/// Iterate through entries.
274	pub fn iter(&self) -> slice::Iter<EntryRef<T>> {
275		self.items.iter()
276	}
277}
278
279/// Delete transaction.
280#[must_use]
281pub struct DeleteTransaction<'a, T> {
282	list: &'a mut RefList<T>,
283	deleted: Vec<usize>,
284}
285
286impl<'a, T> DeleteTransaction<'a, T> {
287	/// Add new element to the delete list.
288	pub fn push(self, idx: usize) -> Self {
289		let mut tx = self;
290		tx.deleted.push(idx);
291		tx
292	}
293
294	/// Commit transaction.
295	pub fn done(self) {
296		let indices = self.deleted;
297		let list = self.list;
298		list.done_delete(&indices[..]);
299	}
300}
301
302/// Insert transaction
303#[must_use]
304pub struct InsertTransaction<'a, T> {
305	at: usize,
306	list: &'a mut RefList<T>,
307	items: Vec<EntryRef<T>>,
308}
309
310impl<'a, T> InsertTransaction<'a, T> {
311	/// Add new element to the delete list.
312	pub fn push(&mut self, val: T) -> EntryRef<T> {
313		let val: EntryRef<_> = Entry::new_detached(val).into();
314		self.items.push(val.clone());
315		val
316	}
317
318	/// Commit transaction.
319	pub fn done(self) {
320		let items = self.items;
321		let list = self.list;
322		let at = self.at;
323		list.done_insert(at, items);
324	}
325}
326
327#[cfg(test)]
328mod tests {
329
330	use super::*;
331
332	#[test]
333	fn order() {
334		let mut list = RefList::<u32>::new();
335		let item00 = list.push(0);
336		let item10 = list.push(10);
337		let item20 = list.push(20);
338		let item30 = list.push(30);
339
340		assert_eq!(item00.order(), Some(0));
341		assert_eq!(item10.order(), Some(1));
342		assert_eq!(item20.order(), Some(2));
343		assert_eq!(item30.order(), Some(3));
344
345		assert_eq!(**item00.read(), 0);
346		assert_eq!(**item10.read(), 10);
347		assert_eq!(**item20.read(), 20);
348		assert_eq!(**item30.read(), 30);
349	}
350
351	#[test]
352	fn delete() {
353		let mut list = RefList::<u32>::new();
354		let item00 = list.push(0);
355		let item10 = list.push(10);
356		let item20 = list.push(20);
357		let item30 = list.push(30);
358
359		list.begin_delete().push(2).done();
360
361		assert_eq!(item00.order(), Some(0));
362		assert_eq!(item10.order(), Some(1));
363		assert_eq!(item30.order(), Some(2));
364
365		// but this was detached
366		assert_eq!(item20.order(), None);
367	}
368
369	#[test]
370	fn complex_delete() {
371		let mut list = RefList::<u32>::new();
372		let item00 = list.push(0);
373		let item10 = list.push(10);
374		let item20 = list.push(20);
375		let item30 = list.push(30);
376		let item40 = list.push(40);
377		let item50 = list.push(50);
378		let item60 = list.push(60);
379		let item70 = list.push(70);
380		let item80 = list.push(80);
381		let item90 = list.push(90);
382
383		list.begin_delete().push(1).push(2).push(4).push(6).done();
384
385		assert_eq!(item00.order(), Some(0));
386		assert_eq!(item10.order(), None);
387		assert_eq!(item20.order(), None);
388		assert_eq!(item30.order(), Some(1));
389		assert_eq!(item40.order(), None);
390		assert_eq!(item50.order(), Some(2));
391		assert_eq!(item60.order(), None);
392		assert_eq!(item70.order(), Some(3));
393		assert_eq!(item80.order(), Some(4));
394		assert_eq!(item90.order(), Some(5));
395	}
396
397	#[test]
398	fn insert() {
399		let mut list = RefList::<u32>::new();
400		let item00 = list.push(0);
401		let item10 = list.push(10);
402		let item20 = list.push(20);
403		let item30 = list.push(30);
404
405		let mut insert_tx = list.begin_insert(3);
406		let item23 = insert_tx.push(23);
407		let item27 = insert_tx.push(27);
408		insert_tx.done();
409
410		assert_eq!(item00.order(), Some(0));
411		assert_eq!(item10.order(), Some(1));
412		assert_eq!(item20.order(), Some(2));
413		assert_eq!(item23.order(), Some(3));
414		assert_eq!(item27.order(), Some(4));
415		assert_eq!(item30.order(), Some(5));
416	}
417
418	#[test]
419	fn insert_end() {
420		let mut list = RefList::<u32>::new();
421
422		let mut insert_tx = list.begin_insert(0);
423		let item0 = insert_tx.push(0);
424		insert_tx.done();
425
426		assert_eq!(item0.order(), Some(0));
427	}
428
429	#[test]
430	fn insert_end_more() {
431		let mut list = RefList::<u32>::new();
432		let item0 = list.push(0);
433
434		let mut insert_tx = list.begin_insert(1);
435		let item1 = insert_tx.push(1);
436		insert_tx.done();
437
438		assert_eq!(item0.order(), Some(0));
439		assert_eq!(item1.order(), Some(1));
440	}
441
442	#[test]
443	fn insert_after() {
444		let mut list = RefList::<u32>::new();
445		let item00 = list.push(0);
446		let item10 = list.push(10);
447		let item20 = list.push(20);
448		let item30 = list.push(30);
449
450		let mut insert_tx = list.begin_insert_after(|i| *i == 20);
451
452		let item23 = insert_tx.push(23);
453		let item27 = insert_tx.push(27);
454		insert_tx.done();
455
456		assert_eq!(item00.order(), Some(0));
457		assert_eq!(item10.order(), Some(1));
458		assert_eq!(item20.order(), Some(2));
459		assert_eq!(item23.order(), Some(3));
460		assert_eq!(item27.order(), Some(4));
461		assert_eq!(item30.order(), Some(5));
462	}
463
464	#[test]
465	fn insert_not_until() {
466		let mut list = RefList::<u32>::new();
467		let item10 = list.push(10);
468		let item20 = list.push(20);
469		let item30 = list.push(30);
470
471		let mut insert_tx = list.begin_insert_not_until(|i| *i <= 20);
472
473		let item23 = insert_tx.push(23);
474		let item27 = insert_tx.push(27);
475		insert_tx.done();
476
477		assert_eq!(item10.order(), Some(0));
478		assert_eq!(item20.order(), Some(1));
479		assert_eq!(item23.order(), Some(2));
480		assert_eq!(item27.order(), Some(3));
481		assert_eq!(item30.order(), Some(4));
482	}
483
484	#[test]
485	fn insert_after_none() {
486		let mut list = RefList::<u32>::new();
487		let item10 = list.push(10);
488		let item20 = list.push(20);
489		let item30 = list.push(30);
490
491		let mut insert_tx = list.begin_insert_after(|i| *i == 50);
492
493		let item55 = insert_tx.push(23);
494		let item59 = insert_tx.push(27);
495		insert_tx.done();
496
497		assert_eq!(item10.order(), Some(0));
498		assert_eq!(item20.order(), Some(1));
499		assert_eq!(item30.order(), Some(2));
500		assert_eq!(item55.order(), Some(3));
501		assert_eq!(item59.order(), Some(4));
502	}
503
504	#[test]
505	fn insert_not_until_none() {
506		let mut list = RefList::<u32>::new();
507		let item10 = list.push(10);
508		let item20 = list.push(20);
509		let item30 = list.push(30);
510
511		let mut insert_tx = list.begin_insert_not_until(|i| *i < 50);
512
513		let item55 = insert_tx.push(23);
514		let item59 = insert_tx.push(27);
515		insert_tx.done();
516
517		assert_eq!(item10.order(), Some(0));
518		assert_eq!(item20.order(), Some(1));
519		assert_eq!(item30.order(), Some(2));
520		assert_eq!(item55.order(), Some(3));
521		assert_eq!(item59.order(), Some(4));
522	}
523
524	#[test]
525	fn insert_after_empty() {
526		let mut list = RefList::<u32>::new();
527
528		let mut insert_tx = list.begin_insert_after(|x| *x == 100);
529		let item0 = insert_tx.push(0);
530		insert_tx.done();
531
532		assert_eq!(item0.order(), Some(0));
533	}
534
535	#[test]
536	fn insert_more() {
537		let mut list = RefList::<u32>::new();
538		let item10 = list.push(10);
539		let item20 = list.push(20);
540		let item30 = list.push(30);
541		let item40 = list.push(10);
542		let item50 = list.push(20);
543		let item60 = list.push(30);
544
545		let mut insert_tx = list.begin_insert(3);
546		let item35 = insert_tx.push(23);
547		let item37 = insert_tx.push(27);
548		insert_tx.done();
549
550		assert_eq!(item10.order(), Some(0));
551		assert_eq!(item20.order(), Some(1));
552		assert_eq!(item30.order(), Some(2));
553		assert_eq!(item35.order(), Some(3));
554		assert_eq!(item37.order(), Some(4));
555		assert_eq!(item40.order(), Some(5));
556		assert_eq!(item50.order(), Some(6));
557		assert_eq!(item60.order(), Some(7));
558	}
559}