0% found this document useful (0 votes)
3 views3 pages

Linked List

The document defines a linked list data structure in Rust, including a Node struct that holds a value and pointers to the next and previous nodes. It implements methods for creating nodes, adding nodes to the list, removing nodes, and iterating over the list. The code includes unsafe memory management practices, such as manual allocation and deallocation of memory for nodes.

Uploaded by

AlbertCG93
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views3 pages

Linked List

The document defines a linked list data structure in Rust, including a Node struct that holds a value and pointers to the next and previous nodes. It implements methods for creating nodes, adding nodes to the list, removing nodes, and iterating over the list. The code includes unsafe memory management practices, such as manual allocation and deallocation of memory for nodes.

Uploaded by

AlbertCG93
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 3

use std::{alloc::{alloc, dealloc, Layout}, marker::{self, PhantomData},

ptr::NonNull};

struct Node<T> {
value: T,
next: Option<NonNull<Node<T>>>,
previous: Option<NonNull<Node<T>>>,
}

impl<T> Node<T> {
fn new(value: T) -> NonNull<Node<T>> {
let layout: Layout = Layout::new::<Node<T>>();

let ptr: *mut Node<T>;


unsafe {
ptr = alloc(layout) as *mut Node<T>;
if ptr.is_null() {
// The allocation failed
// TODO: Implement 'Result' and use it
}

(*ptr).value = value;
(*ptr).next = None;
(*ptr).previous = None;

// No need to use 'new checked' because we ensure it's not null


return NonNull::<Node<T>>::new_unchecked(ptr);
}
}

fn next(&mut self, next: NonNull<Node<T>>) {


self.next = Some(next);

unsafe {
// TODO: Implement 'Result' and use it
(*next.as_ptr()).previous =
Some(NonNull::<Node<T>>::new(self).unwrap());
}
}
}

pub struct LinkedList<'a, T: 'a> {


root: Option<NonNull<Node<T>>>,
last: Option<NonNull<Node<T>>>,
size: u8,
_marker: marker::PhantomData<&'a T>,
}

impl<'a, T: 'a> LinkedList<'a, T> {


pub fn new() -> LinkedList<'a, T> {
return LinkedList {
root: None,
last: None,
size: 0,
_marker: PhantomData {},
}
}

pub fn push_back(&mut self, value: T) {


let node: NonNull<Node<T>> = Node::new(value);

if self.size == 0 {
self.root = Some(node);
self.size += 1;

return;
}

match self.last {
Some(last) => {
unsafe {
(*last.as_ptr()).next = Some(node);
(*node.as_ptr()).previous = Some(last);
}

self.size += 1;
},
None => panic!("TODO: Implement proper error management"),
}
}

// We are not currently checking if the provided 'node' is actually contained


// inside the LinkedList, in order to not decrease performance
// If you were to call this function with an extrenous 'node' the behaviour is
undefined
pub fn remove(&mut self, mut iterator: LinkedListIterator<T>) ->
LinkedListIterator<T> {
// TODO: Manage if the 'unwrap' fails
let node: *mut Node<T> = iterator.value.unwrap().as_ptr();

match self.size {
0 => {
iterator.value = None;
},
1 => {
self.root = None;
self.last = None;
self.size = 0;

let layout: Layout = Layout::new::<Node<T>>();


unsafe {
dealloc(node as *mut u8, layout);
}

iterator.value = None;
},
_ => {
unsafe {
// TODO: Manage if the 'unwrap' fails
(*(*node).previous.unwrap().as_ptr()).next = (*node).next;
self.size -= 1;

iterator.value = (*node).next;

let layout: Layout = Layout::new::<Node<T>>();


dealloc(node as *mut u8, layout);
}
}
}

return iterator;
}

pub fn iter(&self) -> LinkedListIterator<'a, T> {


return LinkedListIterator {
value: self.root,
_marker: PhantomData {},
};
}
}

pub struct LinkedListIterator<'a, T: 'a> {


value: Option<NonNull<Node<T>>>,
_marker: marker::PhantomData<&'a T>,
}

impl<'a, T: 'a> Iterator for LinkedListIterator<'a, T> {


type Item = &'a mut T;

fn next(&mut self) -> Option<Self::Item> {


unsafe {
let next: NonNull<Node<T>> = (*self.value?.as_ptr()).next?;

return Some(&mut (*next.as_ptr()).value);


}
}
}

You might also like