// A simple doubly linked list example using slotmap. use pi_null::Null; use pi_key_alloter::new_key_type; use pi_slotmap::SlotMap; new_key_type! { pub struct ListKey; } #[derive(Copy, Clone)] struct Node { value: T, prev: ListKey, next: ListKey, } pub struct List { sm: SlotMap>, head: ListKey, tail: ListKey, } impl List { pub fn new() -> Self { Self { sm: SlotMap::with_key(), head: ListKey::null(), tail: ListKey::null(), } } pub fn len(&self) -> usize { self.sm.len() } pub fn push_head(&mut self, value: T) -> ListKey { let k = self.sm.insert(Node { value, prev: ListKey::null(), next: self.head, }); if let Some(old_head) = self.sm.get_mut(self.head) { old_head.prev = k; } else { self.tail = k; } self.head = k; k } pub fn push_tail(&mut self, value: T) -> ListKey { let k = self.sm.insert(Node { value, prev: self.tail, next: ListKey::null(), }); if let Some(old_tail) = self.sm.get_mut(self.tail) { old_tail.next = k; } else { self.head = k; } self.tail = k; k } pub fn pop_head(&mut self) -> Option { self.sm.remove(self.head).map(|old_head| { self.head = old_head.next; old_head.value }) } pub fn pop_tail(&mut self) -> Option { self.sm.remove(self.tail).map(|old_tail| { self.tail = old_tail.prev; old_tail.value }) } pub fn remove(&mut self, key: ListKey) -> Option { self.sm.remove(key).map(|node| { if let Some(prev_node) = self.sm.get_mut(node.prev) { prev_node.next = node.next; } else { self.head = node.next; } if let Some(next_node) = self.sm.get_mut(node.next) { next_node.prev = node.prev; } else { self.tail = node.prev; } node.value }) } pub fn head(&self) -> ListKey { self.head } pub fn tail(&self) -> ListKey { self.tail } pub fn get(&self, key: ListKey) -> Option<&T> { self.sm.get(key).map(|node| &node.value) } pub fn get_mut(&mut self, key: ListKey) -> Option<&mut T> { self.sm.get_mut(key).map(|node| &mut node.value) } } fn main() { let mut dll = List::new(); dll.push_head(5); dll.push_tail(6); let k = dll.push_head(3); dll.push_tail(7); dll.push_head(4); assert_eq!(dll.len(), 4); assert_eq!(dll.pop_head(), Some(4)); assert_eq!(dll.pop_head(), Some(5)); assert_eq!(dll.head(), k); dll.push_head(10); assert_eq!(dll.remove(k), Some(3)); assert_eq!(dll.pop_tail(), Some(7)); assert_eq!(dll.pop_tail(), Some(6)); assert_eq!(dll.pop_head(), Some(10)); assert_eq!(dll.pop_head(), None); assert_eq!(dll.pop_tail(), None); }