#[cfg(test)]
mod tests;
mod node;
use node::Node;
use std::boxed::Box;
use core::option::Option;
use core::ptr::NonNull;
pub struct DoublyLinkedList<T> {
head: Option<NonNull<Node<T>>>,
tail: Option<NonNull<Node<T>>>,
len: usize,
}
impl<T> DoublyLinkedList<T> {
#[inline]
pub const fn new() -> Self {
return Self {
head: None,
tail: None,
len: 0,
};
}
#[inline]
pub const fn len(&self) -> usize {
return self.len;
}
#[inline]
pub fn clear(&mut self) {
*self = Self::new();
}
#[inline]
pub fn front(&self) -> Option<&T> {
return match self.head {
Some(ptr) => unsafe { Some(&ptr.as_ref().value) },
None => None,
}
}
#[inline]
pub fn back(&self) -> Option<&T> {
return match self.tail {
Some(ptr) => unsafe { Some(&ptr.as_ref().value) },
None => None,
}
}
#[inline]
pub fn front_mut(&mut self) -> Option<&mut T> {
return match self.head {
Some(mut ptr) => unsafe { Some(&mut ptr.as_mut().value) },
None => None,
}
}
#[inline]
pub fn back_mut(&mut self) -> Option<&mut T> {
return match self.tail {
Some(mut ptr) => unsafe { Some(&mut ptr.as_mut().value) },
None => None,
}
}
#[inline]
pub fn push_front(&mut self, value: T) {
let mut new_node = Node::new(value).into_box();
new_node.next = self.head;
let node_ptr = unsafe {
Some(NonNull::new_unchecked(Box::into_raw(new_node)))
};
match self.head {
Some(mut ptr) => unsafe { ptr.as_mut().prev = node_ptr; },
None => { self.tail = node_ptr; },
}
self.len += 1;
self.head = node_ptr;
}
#[inline]
pub fn push_back(&mut self, value: T) {
let mut new_node = Node::new(value).into_box();
new_node.prev = self.tail;
let node_ptr = unsafe {
Some(NonNull::new_unchecked(Box::into_raw(new_node)))
};
match self.tail {
Some(mut ptr) => unsafe { ptr.as_mut().next = node_ptr; },
None => { self.head = node_ptr; },
}
self.len += 1;
self.tail = node_ptr;
}
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
if index == 0 { return self.front(); }
if index == self.len - 1 { return self.back(); }
let mut current = self.head;
let mut i = 0;
while let Some(ptr) = current {
let node = unsafe { ptr.as_ref() };
if i == index {
return Some(&node.value);
}
current = node.next;
i += 1;
}
return None;
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index == 0 { return self.front_mut(); }
if index == self.len - 1 { return self.back_mut(); }
let mut current = self.head;
let mut i = 0;
while let Some(mut ptr) = current {
let node = unsafe { ptr.as_mut() };
if i == index {
return Some(&mut node.value);
}
current = node.next;
i += 1;
}
return None;
}
}