From b58312c19684d91fe9df94c13fb4f89e717bd938 Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Fri, 6 Aug 2021 22:45:04 +0200 Subject: [PATCH] get --- src/linked_list.rs | 86 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/src/linked_list.rs b/src/linked_list.rs index 914a58a..dd3295e 100644 --- a/src/linked_list.rs +++ b/src/linked_list.rs @@ -1,5 +1,9 @@ +use std::fmt::Debug; use std::ptr::NonNull; +type NodePtr = Option>>; + +/// A doubly linked list with unsafe :O, except it's kind of shit compared to the std one #[derive(Debug)] pub struct LinkedList { start: Option>>, @@ -15,19 +19,66 @@ where } } +#[derive(Debug)] pub struct Node { value: T, - next: Option>>, - prev: Option>>, + next: NodePtr, + prev: NodePtr, } impl LinkedList { - pub fn new() -> Self { + /// Creates a new empty Linked List + pub fn new() -> LinkedList { Self { start: None, end: None, } } + + /// Prepend an element to the start of the list + pub fn prepend(&mut self, element: T) { + match self.start { + None => { + let node = allocate_nonnull(Node { + value: element, + next: None, + prev: None, + }); + self.start = Some(node); + self.end = Some(node); + } + Some(mut node) => { + let new = allocate_nonnull(Node { + value: element, + next: Some(node), + prev: None, + }); + unsafe { node.as_mut() }.prev = Some(new); + } + } + } + + /// Random access over the list + pub fn get(&self, index: usize) -> Option<&T> { + dbg!(self); + Self::get_inner(self.start.as_ref(), index).map(|n| &n.value) + } + + fn get_inner(node: Option<&NonNull>>, index: usize) -> Option<&Node> { + if let Some(ptr) = node { + match index { + 0 => unsafe { Some(ptr.as_ref()) }, + n => LinkedList::get_inner(Some(ptr), n - 1), + } + } else { + None + } + } +} + +fn allocate_nonnull(element: T) -> NonNull { + let mut boxed = Box::new(element); + NonNull::new(boxed.as_mut()).expect("Allocation returned null pointer") } impl IntoIterator for LinkedList { @@ -40,7 +91,7 @@ impl IntoIterator for LinkedList { } pub struct IntoIter { - item: Option>>, + item: NodePtr, } impl IntoIter { @@ -53,12 +104,29 @@ impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { - let next = self.item.take(); - let ptr = match next { - None => return None, - Some(mut ptr) => unsafe { ptr.as_mut() }, - }; + //let next = self.item.take(); + //let ptr = match next { + // None => return None, + // Some(mut ptr) => unsafe { ptr.as_mut() }, + //}; todo!() } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn random_access() { + let mut list = LinkedList::new(); + list.prepend("hallo"); + list.prepend("test"); + list.prepend("nice"); + assert_eq!(list.get(0), Some(&"nice")); + assert_eq!(list.get(1), Some(&"test")); + assert_eq!(list.get(2), Some(&"hallo")); + assert_eq!(list.get(3), None); + } +}