use std::ptr;
pub struct Node<T> {
next: Option<ptr::NonNull<Node<T>>>,
prev: Option<ptr::NonNull<Node<T>>>,
pub value: T,
}
impl<T> Node<T> {
pub fn new(value: T) -> Self {
Self {
next: None,
prev: None,
value,
}
}
}
pub struct LinkedList<T> {
first: Option<ptr::NonNull<Node<T>>>,
last: Option<ptr::NonNull<Node<T>>>,
}
impl<T> LinkedList<T> {
pub fn new() -> Self {
Self {
first: None,
last: None,
}
}
pub fn is_empty(&self) -> bool {
self.first.is_none()
}
pub fn steal(&mut self) -> Self {
Self {
first: self.first.take(),
last: self.last.take(),
}
}
pub unsafe fn push_front(&mut self, mut node: ptr::NonNull<Node<T>>) -> bool {
if let Some(mut first) = self.first.take() {
node.as_mut().next = Some(first);
first.as_mut().prev = Some(node);
self.first = Some(node);
false
} else {
self.first = Some(node);
self.last = Some(node);
true
}
}
pub unsafe fn push_back(&mut self, mut node: ptr::NonNull<Node<T>>) -> bool {
if let Some(mut last) = self.last.take() {
node.as_mut().prev = Some(last);
last.as_mut().next = Some(node);
self.last = Some(node);
false
} else {
self.first = Some(node);
self.last = Some(node);
true
}
}
pub unsafe fn pop_front(&mut self) -> Option<ptr::NonNull<Node<T>>> {
let mut first = self.first?;
if let Some(mut next) = first.as_mut().next.take() {
next.as_mut().prev = None;
self.first = Some(next);
} else {
self.first = None;
self.last = None;
}
debug_assert!(first.as_ref().prev.is_none());
debug_assert!(first.as_ref().next.is_none());
Some(first)
}
pub unsafe fn pop_back(&mut self) -> Option<ptr::NonNull<Node<T>>> {
let mut last = self.last?;
if let Some(mut prev) = last.as_mut().prev.take() {
prev.as_mut().next = None;
self.last = Some(prev);
} else {
self.first = None;
self.last = None;
}
debug_assert!(last.as_ref().prev.is_none());
debug_assert!(last.as_ref().next.is_none());
Some(last)
}
}