Files
another-boids-in-rust/vendor/slotmap/examples/doubly_linked_list.rs

136 lines
3.2 KiB
Rust

// A simple doubly linked list example using slotmap.
use slotmap::{new_key_type, Key, SlotMap};
new_key_type! {
pub struct ListKey;
}
#[derive(Copy, Clone)]
struct Node<T> {
value: T,
prev: ListKey,
next: ListKey,
}
pub struct List<T> {
sm: SlotMap<ListKey, Node<T>>,
head: ListKey,
tail: ListKey,
}
impl<T> List<T> {
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<T> {
self.sm.remove(self.head).map(|old_head| {
self.head = old_head.next;
old_head.value
})
}
pub fn pop_tail(&mut self) -> Option<T> {
self.sm.remove(self.tail).map(|old_tail| {
self.tail = old_tail.prev;
old_tail.value
})
}
pub fn remove(&mut self, key: ListKey) -> Option<T> {
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);
}