#[cfg(test)]
mod tests;
mod node;
use node::Node;
use std::boxed::Box;
use core::ptr::{NonNull, read as ptr_read};
use core::iter::{Iterator, IntoIterator, ExactSizeIterator};
use core::cmp::{Eq, PartialEq};
use core::option::Option;
use core::fmt;
pub struct SinglyLinkedList<T> {
head: Option<NonNull<Node<T>>>,
len: usize,
}
pub struct Iter<T> {
list: SinglyLinkedList<T>,
}
impl<T> Iterator for Iter<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
return self.list.pop_front();
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
return (self.list.len(), Some(self.list.len()));
}
}
impl<T> ExactSizeIterator for Iter<T> { }
impl<T> SinglyLinkedList<T> {
#[inline]
pub const fn new() -> Self {
return Self {
head: 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> {
if let Some(ptr) = self.head {
let mut current = Some(ptr);
while let Some(ptr) = current {
let node = unsafe { ptr.as_ref() };
if node.next.is_none() {
return Some(&node.value);
}
current = node.next;
}
}
return 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> {
if let Some(ptr) = self.head {
let mut current = Some(ptr);
while let Some(mut ptr) = current {
let node = unsafe { ptr.as_mut() };
if node.next.is_none() {
return Some(&mut node.value);
}
current = node.next;
}
}
return 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 ptr = unsafe {
NonNull::new_unchecked(Box::into_raw(new_node))
};
self.len += 1;
self.head = Some(ptr);
}
#[inline]
pub fn push_back(&mut self, value: T) {
let ptr = unsafe {
NonNull::new_unchecked(
Box::into_raw(Node::new(value).into_box())
)
};
match self.head {
Some(x) => unsafe {
let mut current = Some(x);
while let Some(mut x) = current {
let m = x.as_mut();
if m.next.is_none() {
m.next = Some(ptr);
break;
}
current = m.next;
}
},
None => self.head = Some(ptr),
}
self.len += 1
}
#[inline]
pub fn pop_front(&mut self) -> Option<T> {
return match self.head {
Some(mut ptr) => unsafe {
let node = ptr_read(&mut (*ptr.as_mut()));
self.head = node.next;
self.len -= 1;
Some(node.value)
},
None => None,
};
}
#[inline]
pub fn remove_front(&mut self) {
let _ = self.pop_front();
}
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
if index == 0 { return self.front(); }
if index >= self.len { return None; }
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 { return None; }
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;
}
}
impl<T> IntoIterator for SinglyLinkedList<T> {
type Item = T;
type IntoIter = Iter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
return Iter { list: self };
}
}
impl<T: PartialEq> PartialEq for SinglyLinkedList<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() { return false; }
if self.len() == 0 { return true; }
let mut s = self.head;
let mut o = other.head;
while let (Some(a), Some(b)) = (s, o) {
let a = unsafe { a.as_ref() };
let b = unsafe { b.as_ref() };
if a.value != b.value { return false; }
s = a.next;
o = b.next;
}
return true;
}
}
impl<T: Eq> Eq for SinglyLinkedList<T> { }
impl<T: fmt::Debug> fmt::Debug for SinglyLinkedList<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
return f.debug_struct("SinglyLinkedList")
.field("head", &self.head)
.field("len", &self.len)
.finish();
}
}