mirror of
https://github.com/fluencelabs/wasm-utils
synced 2025-04-21 12:52:23 +00:00
ref list impl
This commit is contained in:
parent
80d80a37d9
commit
db4070b96c
@ -19,6 +19,7 @@ mod ext;
|
|||||||
mod pack;
|
mod pack;
|
||||||
mod runtime_type;
|
mod runtime_type;
|
||||||
mod graph;
|
mod graph;
|
||||||
|
mod ref_list;
|
||||||
|
|
||||||
pub mod stack_height;
|
pub mod stack_height;
|
||||||
|
|
||||||
|
181
src/ref_list.rs
Normal file
181
src/ref_list.rs
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EntryRef<T>(Rc<RefCell<Entry<T>>>);
|
||||||
|
|
||||||
|
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> {
|
||||||
|
fn read(&self) -> ::std::cell::Ref<Entry<T>> {
|
||||||
|
self.0.borrow()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self) -> ::std::cell::RefMut<Entry<T>> {
|
||||||
|
self.0.borrow_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn order(&self) -> Option<usize> {
|
||||||
|
self.0.borrow().order()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RefList<T> {
|
||||||
|
items: Vec<EntryRef<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> RefList<T> {
|
||||||
|
|
||||||
|
pub fn new() -> Self { RefList { items: Default::default() } }
|
||||||
|
|
||||||
|
fn push(&mut self, t: T) -> EntryRef<T> {
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn done_delete(&mut self, indices: &[usize]) {
|
||||||
|
|
||||||
|
let mut index = 0;
|
||||||
|
|
||||||
|
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; },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete(&mut self, inddices: &[usize]) {
|
||||||
|
self.done_delete(inddices)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_one(&mut self, index: usize) {
|
||||||
|
self.done_delete(&[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub struct DeleteTransaction<'a, T> {
|
||||||
|
list: &'a mut RefList<T>,
|
||||||
|
deleted: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> DeleteTransaction<'a, T> {
|
||||||
|
pub fn push(mut self, idx: usize) -> Self {
|
||||||
|
let mut tx = self;
|
||||||
|
tx.deleted.push(idx);
|
||||||
|
tx
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn done(mut self) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user