use value_pool::{smart_value_pool::SmartValuePool, ValuePool, ValueRef}; #[derive(Debug, Clone)] struct Node { value: T, next: Option>>, } impl Node { fn new(value: T, next: Option>>) -> Node { Node { value, next } } } #[derive(Debug)] struct LinkedList { start: ValueRef>, end: ValueRef>, store: SmartValuePool, Self>, } // Not needed fn on_empty(_pool: &mut ValuePool>, _ll: &mut LinkedList) {} // ensures that on we always have a valid state when we start from an empty LinkedList fn on_empty_push( _pool: &mut ValuePool>, reference: ValueRef>, ll: &mut LinkedList, ) { ll.start = reference; ll.end = reference; } impl LinkedList { pub fn new() -> LinkedList { // We can use a ValueRef equal to 0 and then check in all methods if `store.is_empty` LinkedList { start: (ValueRef::default()), end: (ValueRef::default()), store: (SmartValuePool::make_smart(ValuePool::new(), on_empty, on_empty_push)), } } pub fn push_back(&mut self, value: T) -> Option<()> { // will return Option<()> here for ease of use // think of reference as a weird "pointer" // If `self.store.is_empty`, then `self.start` and `self.end` will be send let reference = self.store.push(Node::new(value, None)); self.store.get_mut(self.end)?.next = Some(reference); self.end = reference; Some(()) } pub fn pop_front(&mut self) -> Option { // will return Option here in case self.store is empty if self.store.is_empty() { return None; } // We expect that `self.store.take(self.start)` returns Some(...) if our LinkedList is in a valid state. // We could use `unwrap_unchecked` if we can guarantee that our LinkedList is in such a state or if we don't care about our safety. // Or we remove our first check if `self.store.is_empty` and just use the `?` (`self.store.take` will return None if it's empty) let first_node = self.store.take(self.start)?; // We can't use `.unwrap` or `?` here, because `first_node` could have no `first_node.next` node. // We don't want a panic or early return. We want to return `first_node.value`. // Note: `ValueRef::default() == ValueRef::new(0)` self.start = first_node.next.unwrap_or_default(); Some(first_node.value) } } fn main() { let example_data = [1, 2, 3, 12, 2, 1, 4, 22, 8, 19]; let mut ll: LinkedList = LinkedList::new(); println!("Creating a populated Linked List"); for i in example_data.iter() { assert!(ll.push_back(*i).is_some()); } println!("Our Linked List as debug print: {:#?}", &ll); println!("first element: {}", ll.pop_front().unwrap()); }