wasm-utils/src/ref_list.rs

227 lines
4.2 KiB
Rust
Raw Normal View History

2019-01-22 12:08:25 +03:00
use std::rc::Rc;
use std::cell::RefCell;
2019-01-22 14:31:21 +03:00
use std::vec::Vec;
2019-01-22 12:08:25 +03:00
#[derive(Debug)]
enum EntryOrigin {
Index(usize),
Detached,
}
impl From<usize> for EntryOrigin {
fn from(v: usize) -> Self {
EntryOrigin::Index(v)
}
}
#[derive(Debug)]
pub struct Entry<T> {
val: T,
index: EntryOrigin,
}
impl<T> Entry<T> {
fn new(val: T, index: usize) -> Entry<T> {
Entry {
val: val,
index: EntryOrigin::Index(index),
}
}
pub fn order(&self) -> Option<usize> {
match self.index {
EntryOrigin::Detached => None,
EntryOrigin::Index(idx) => Some(idx),
}
}
}
impl<T> ::std::ops::Deref for Entry<T> {
type Target = T;
fn deref(&self) -> &T {
&self.val
}
}
2019-01-22 20:30:50 +03:00
impl<T> ::std::ops::DerefMut for Entry<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.val
}
}
2019-01-22 12:19:29 +03:00
pub struct EntryRef<T>(Rc<RefCell<Entry<T>>>);
2019-01-22 12:08:25 +03:00
impl<T> Clone for EntryRef<T> {
fn clone(&self) -> Self {
EntryRef(self.0.clone())
}
}
impl<T> From<Entry<T>> for EntryRef<T> {
fn from(v: Entry<T>) -> Self {
EntryRef(Rc::new(RefCell::new(v)))
}
}
impl<T> EntryRef<T> {
2019-01-22 14:31:21 +03:00
pub fn read(&self) -> ::std::cell::Ref<Entry<T>> {
2019-01-22 12:08:25 +03:00
self.0.borrow()
}
2019-01-22 14:31:21 +03:00
pub fn write(&self) -> ::std::cell::RefMut<Entry<T>> {
2019-01-22 12:08:25 +03:00
self.0.borrow_mut()
}
2019-01-22 14:31:21 +03:00
pub fn order(&self) -> Option<usize> {
2019-01-22 12:08:25 +03:00
self.0.borrow().order()
}
2019-01-22 14:31:21 +03:00
pub fn link_count(&self) -> usize {
Rc::strong_count(&self.0) - 1
}
2019-01-22 12:08:25 +03:00
}
2019-01-22 12:19:29 +03:00
pub struct RefList<T> {
2019-01-22 12:08:25 +03:00
items: Vec<EntryRef<T>>,
}
2019-01-22 12:19:29 +03:00
impl<T> Default for RefList<T> {
fn default() -> Self {
RefList { items: Default::default() }
}
}
2019-01-22 12:08:25 +03:00
impl<T> RefList<T> {
2019-01-22 12:19:29 +03:00
pub fn new() -> Self { Self::default() }
2019-01-22 12:08:25 +03:00
2019-01-22 12:19:29 +03:00
pub fn push(&mut self, t: T) -> EntryRef<T> {
2019-01-22 12:08:25 +03:00
let idx = self.items.len();
let val: EntryRef<_> = Entry::new(t, idx).into();
self.items.push(val.clone());
val
}
pub fn begin_delete(&mut self) -> DeleteTransaction<T> {
DeleteTransaction {
list: self,
deleted: Vec::new(),
}
}
2019-01-22 12:19:29 +03:00
pub fn get(&self, idx: usize) -> Option<EntryRef<T>> {
self.items.get(idx).cloned()
}
2019-01-22 12:08:25 +03:00
fn done_delete(&mut self, indices: &[usize]) {
for idx in indices {
let mut detached = self.items.remove(*idx);
detached.write().index = EntryOrigin::Detached;
}
for index in 0..self.items.len() {
let mut next_entry = self.items.get_mut(index).expect("Checked above; qed").write();
let total_less = indices.iter()
.take_while(|x| **x < next_entry.order().expect("Items in the list always have order; qed"))
.count();
match next_entry.index {
EntryOrigin::Detached => unreachable!("Items in the list always have order!"),
EntryOrigin::Index(ref mut idx) => { *idx -= total_less; },
};
}
}
2019-01-22 12:19:29 +03:00
pub fn delete(&mut self, indices: &[usize]) {
self.done_delete(indices)
2019-01-22 12:08:25 +03:00
}
pub fn delete_one(&mut self, index: usize) {
self.done_delete(&[index])
}
2019-01-22 12:19:29 +03:00
pub fn from_slice(list: &[T]) -> Self
where T: Clone
{
let mut res = Self::new();
for t in list {
res.push(t.clone());
}
res
}
2019-01-22 12:58:29 +03:00
pub fn len(&self) -> usize {
self.items.len()
}
2019-01-22 14:31:21 +03:00
pub fn clone_ref(&self, idx: usize) -> EntryRef<T> {
self.items[idx].clone()
}
pub fn get_ref(&self, idx: usize) -> &EntryRef<T> {
&self.items[idx]
}
2019-01-22 16:11:04 +03:00
pub fn iter(&self) -> std::slice::Iter<EntryRef<T>> {
self.items.iter()
}
2019-01-22 12:08:25 +03:00
}
#[must_use]
pub struct DeleteTransaction<'a, T> {
list: &'a mut RefList<T>,
deleted: Vec<usize>,
}
impl<'a, T> DeleteTransaction<'a, T> {
2019-01-22 18:28:15 +03:00
pub fn push(self, idx: usize) -> Self {
2019-01-22 12:08:25 +03:00
let mut tx = self;
tx.deleted.push(idx);
tx
}
2019-01-22 18:28:15 +03:00
pub fn done(self) {
2019-01-22 12:08:25 +03:00
let indices = self.deleted;
let list = self.list;
list.done_delete(&indices[..]);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn order() {
let mut list = RefList::<u32>::new();
let item10 = list.push(10);
let item20 = list.push(20);
let item30 = list.push(30);
assert_eq!(item10.order(), Some(0usize));
assert_eq!(item20.order(), Some(1));
assert_eq!(item30.order(), Some(2));
assert_eq!(**item10.read(), 10);
assert_eq!(**item20.read(), 20);
assert_eq!(**item30.read(), 30);
}
#[test]
fn delete() {
let mut list = RefList::<u32>::new();
let item10 = list.push(10);
let item20 = list.push(20);
let item30 = list.push(30);
list.begin_delete().push(1).done();
assert_eq!(item10.order(), Some(0));
assert_eq!(item30.order(), Some(1));
assert_eq!(item20.order(), None);
}
}