use std::fmt::{Debug};
use crate::linked_list::iter::{IntoIter, Iter, IterMut};
use crate::linked_list::linked_list_error::LinkedListError;
use crate::linked_list::node::Node;
use crate::linked_list::traits::linked_list_traits::LinkedListTrait;
#[derive(PartialEq, Clone)]
pub struct LinkedList<T>{
first:Option<Box<Node<T>>>,
size:usize
}
impl <T:PartialEq> LinkedListTrait<T> for LinkedList<T> {
fn new()-> LinkedList<T> {
LinkedList{first:None, size:0}
}
fn from_vec(values: Vec<T>)->LinkedList<T> {
let mut list = LinkedList::new();
for value in values{
list.push(value);
}
list
}
fn push(&mut self, value: T){
self.insert(value, self.size()).ok();
}
fn insert(&mut self, value: T, index: usize)-> Result<(), LinkedListError> {
if index > self.size{
return Err(LinkedListError::OutOfBounds { index });
}
let mut node = Node::new(value);
if self.first.is_none(){
self.first = Some(Box::new(node));
}
else if index == 0{
node.next = self.first.take();
self.first = Some(Box::new(node));
}
else{
let mut temp = self.first.as_mut().unwrap(); for _ in 0..index - 1 {
temp = temp.next.as_mut().unwrap();
}
let prev_next = temp.next.take();
node.next = prev_next;
temp.next = Some(Box::new(node));
}
self.size += 1;
Ok(())
}
fn remove(&mut self, index: usize) -> Result<T, LinkedListError>{
if index >= self.size(){
return Err(LinkedListError::OutOfBounds { index });
}
let removed_value;
if index == 0 {
let node = self.first.take().unwrap();
removed_value = node.value;
self.first = node.next;
}
else if index == self.size() - 1 {
let last = self.get_node_mut(self.size() - 2);
let node = last.next.take().unwrap();
removed_value = node.value;
}
else {
let node_before = self.get_node_mut(index - 1);
let node_to_remove = node_before.next.take().unwrap();
node_before.next = node_to_remove.next;
removed_value = node_to_remove.value;
}
self.size -= 1;
Ok(removed_value)
}
fn get(&self, index: usize) -> Result<&T, LinkedListError> {
if index >= self.size(){
return Err(LinkedListError::OutOfBounds { index });
}
Ok(&self.get_node(index).value)
}
fn get_mut(&mut self, index: usize) -> Result<&mut T, LinkedListError> {
if index >= self.size(){
return Err(LinkedListError::OutOfBounds { index });
}
Ok(&mut self.get_node_mut(index).value)
}
fn contains(&self, value:&T)->bool{
let mut next = self.first.as_deref();
while let Some(node) = next{
if &node.value == value{
return true;
}
next = node.next.as_deref();
}
return false;
}
fn size(&self) -> usize {
return self.size;
}
fn iter(&self) -> Iter<'_, T> {
Iter {
current: self.first.as_deref(),
}
}
fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
current: self.first.as_deref_mut(),
}
}
fn is_empty(&self)->bool {
return self.size() == 0;
}
}
impl <T> LinkedList<T>{
fn get_node(&self, index: usize) -> &Node<T>{
if index >= self.size{
panic!("Index out of bounds error"); }
let mut temp = self.first.as_ref().unwrap();
for _ in 0..index {
temp = temp.next.as_ref().unwrap();
}
&temp
}
fn get_node_mut(&mut self, index: usize) -> &mut Node<T>{
if index >= self.size{
panic!("Index out of bounds error");
}
let mut temp = self.first.as_mut().unwrap();
for _ in 0..index {
temp = temp.next.as_mut().unwrap();
}
temp
}
}
impl<T> IntoIterator for LinkedList<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {current:self.first}
}
}
impl<'a, T> IntoIterator for &'a LinkedList<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
Iter {
current: self.first.as_deref(),
}
}
}
impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
IterMut {
current: self.first.as_deref_mut(),
}
}
}
impl<T:PartialEq> FromIterator<T> for LinkedList<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut list = LinkedList::new();
for item in iter {
list.push(item);
}
list
}
}
impl <T:Debug> Debug for LinkedList<T>{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut temp = self.first.as_ref();
write!(f, "[")?;
while let Some(node) = temp{
if node.next.is_none(){
write!(f, "{:?}", node.value)?;
break;
}
write!(f, "{:?}, ", node.value)?;
temp = node.next.as_ref();
}
write!(f, "]")?;
Ok(())
}
}