use obj_pool::{ObjId, ObjPool};
struct Node<T> {
prev: Option<ObjId>,
next: Option<ObjId>,
value: T,
}
struct List<T> {
obj_pool: ObjPool<Node<T>>,
head: Option<ObjId>,
tail: Option<ObjId>,
}
impl<T> List<T> {
fn new() -> Self {
List {
obj_pool: ObjPool::new(),
head: None,
tail: None,
}
}
fn len(&self) -> usize {
self.obj_pool.len() as usize
}
fn link(&mut self, a: Option<ObjId>, b: Option<ObjId>) {
if let Some(a) = a {
self.obj_pool[a].next = b;
}
if let Some(b) = b {
self.obj_pool[b].prev = a;
}
}
fn push_back(&mut self, value: T) -> usize {
let node = self.obj_pool.insert(Node {
prev: None,
next: None,
value,
});
let tail = self.tail;
self.link(tail, Some(node));
self.tail = Some(node);
if self.head.is_none() {
self.head = Some(node);
}
self.obj_pool.obj_id_to_index(node) as usize
}
fn pop_front(&mut self) -> T {
let head = self.head.expect("the list is empty");
let node = self.obj_pool.remove(head).unwrap();
self.link(None, node.next);
self.head = node.next;
if node.next.is_none() {
self.tail = None;
}
node.value
}
fn remove(&mut self, index: usize) -> T {
let obj_id = self.obj_pool.index_to_obj_id(index as u32);
let node = self.obj_pool.remove(obj_id).unwrap();
self.link(node.prev, node.next);
if self.head == Some(obj_id) {
self.head = node.next;
}
if self.tail == Some(obj_id) {
self.tail = node.prev;
}
node.value
}
}
fn main() {
let mut list = List::new();
let one = list.push_back(1);
list.push_back(2);
list.push_back(3);
list.push_back(10);
let twenty = list.push_back(20);
list.push_back(30);
assert_eq!(list.len(), 6);
assert_eq!(list.remove(one), 1);
assert_eq!(list.remove(twenty), 20);
assert_eq!(list.len(), 4);
assert_eq!(list.pop_front(), 2);
assert_eq!(list.pop_front(), 3);
assert_eq!(list.pop_front(), 10);
assert_eq!(list.pop_front(), 30);
assert_eq!(list.len(), 0);
}