diff --git a/src/es06_list.rs b/src/es06_list.rs index 73086ba..234447a 100644 --- a/src/es06_list.rs +++ b/src/es06_list.rs @@ -38,9 +38,7 @@ impl DoublyPointedList { } */ use std::{ - cell::{RefCell, RefMut}, - fmt::Debug, - rc::Rc, + cell::{RefCell, RefMut}, fmt::Debug, mem, rc::Rc }; type Pointer = Option>>; @@ -53,8 +51,8 @@ pub struct LinkedList { struct Node { element: T, - next: Pointer>, - prev: Pointer>, + next: Pointer, + prev: Pointer, } impl Node { @@ -65,9 +63,6 @@ impl Node { prev: None, } } - pub fn get(node: &Rc>>) -> RefMut> { - node.as_ref().borrow_mut() - } pub fn as_memref(self) -> Rc>> { Rc::new(RefCell::new(self)) } @@ -93,8 +88,8 @@ impl LinkedList { pub fn push_front(&mut self, element: T) { let element = Node::new(element).as_memref(); if let Some(head) = self.head.take() { - Node::get(&head).prev = Some(element.clone()); - Node::get(&element).next = Some(head); + head.borrow_mut().prev = Some(element.clone()); + element.borrow_mut().next = Some(head); } else { self.tail = Some(element.clone()); } @@ -105,8 +100,8 @@ impl LinkedList { pub fn push_back(&mut self, element: T) { let element = Node::new(element).as_memref(); if let Some(tail) = self.tail.take() { - Node::get(&tail).next = Some(element.clone()); - Node::get(&element).prev = Some(tail); + tail.borrow_mut().next = Some(element.clone()); + element.borrow_mut().prev = Some(tail); } else { self.head = Some(element.clone()); } @@ -116,47 +111,46 @@ impl LinkedList { } pub fn pop_front(&mut self) -> Option { - if let Some(node) = self.head.take() { - let node = Node::get(&node); - self.head = node.next.clone(); - - match self.head.as_ref() { - Some(other) => Node::get(other).prev = None, - _ => self.tail = None, - } - - self.size -= 1; - return Some(node.element); - } - None + self.remove(0) } pub fn pop_back(&mut self) -> Option { - if let Some(node) = self.tail.take() { - let node = Node::get(&node); - self.tail = node.prev.clone(); + self.remove(-1) + } - match self.tail.as_ref() { - Some(other) => Node::get(other).next = None, - _ => self.head = None, + fn remove(&mut self, n: i32) -> Option { + let index = n + if n < 0 { self.size as i32 } else { 0 }; + if let Some(node) = self.find(index) { + let node = node.borrow_mut(); + let prev = node.prev.clone(); + let next = node.next.clone(); + + match &prev { + Some(val) => val.borrow_mut().next = next.clone(), + None => self.head = next.clone(), + } + match &next { + Some(val) => val.borrow_mut().prev = prev.clone(), + None => self.tail = prev.clone(), } self.size -= 1; - return Some(node.element); + Some(node.element) + } else { + None } - None } pub fn get_front(&self) -> Option { - self.head.clone().and_then(|h| Some(Node::get(&h).element)) + self.head.clone().and_then(|h| Some(h.borrow_mut().element)) } pub fn get_back(&self) -> Option { - self.tail.clone().and_then(|t| Some(Node::get(&t).element)) + self.tail.clone().and_then(|t| Some(t.borrow_mut().element)) } pub fn get(&self, n: i32) -> Option { let index = n + if n < 0 { self.size as i32 } else { 0 }; if let Some(node) = self.find(index) { - Some(Node::get(&node).element) + Some(node.borrow_mut().element) } else { None } diff --git a/src/es07_list_generic.rs b/src/es07_list_generic.rs index 97f10ba..51164ae 100644 --- a/src/es07_list_generic.rs +++ b/src/es07_list_generic.rs @@ -55,23 +55,20 @@ pub struct LinkedList { #[derive(Debug)] struct Node { - element: Option, - next: Pointer>, - prev: Pointer>, + element: T, + next: Pointer, + prev: Pointer, } impl Node { pub fn new(element: T) -> Self { Self { - element: Some(element), + element, next: None, prev: None, } } - pub fn get(node: &Rc>>) -> RefMut> { - node.as_ref().borrow_mut() - } - pub fn as_memref(self) -> Rc>> { + pub fn as_memref(self) -> Rc> { Rc::new(RefCell::new(self)) } } @@ -96,8 +93,8 @@ impl LinkedList { pub fn push_front(&mut self, element: T) { let element = Node::new(element).as_memref(); if let Some(head) = self.head.take() { - Node::get(&head).prev = Some(element.clone()); - Node::get(&element).next = Some(head); + head.borrow_mut().prev = Some(element.clone()); + element.borrow_mut().next = Some(head); } else { self.tail = Some(element.clone()); } @@ -108,8 +105,8 @@ impl LinkedList { pub fn push_back(&mut self, element: T) { let element = Node::new(element).as_memref(); if let Some(tail) = self.tail.take() { - Node::get(&tail).next = Some(element.clone()); - Node::get(&element).prev = Some(tail); + tail.borrow_mut().next = Some(element.clone()); + element.borrow_mut().prev = Some(tail); } else { self.head = Some(element.clone()); } @@ -128,24 +125,22 @@ impl LinkedList { pub fn get(&mut self, n: i32) -> Option { let index = n + if n < 0 { self.size as i32 } else { 0 }; if let Some(node) = self.find(index) { - let mut node = Node::get(&node); - let prev = node.prev.clone(); - let next = node.next.clone(); + let temp = node.borrow_mut(); + let prev = temp.prev.clone(); + let next = temp.next.clone(); + mem::drop(temp); // drop the borrow match &prev { - Some(val) => Node::get(val).next = next.clone(), + Some(val) => val.borrow_mut().next = next.clone(), None => self.head = next.clone(), } match &next { - Some(val) => Node::get(val).prev = prev.clone(), + Some(val) => val.borrow_mut().prev = prev.clone(), None => self.tail = prev.clone(), } self.size -= 1; - // Non avessi usato Option avrei dovuto usare unsafe { mem::zeroed::() } - // ma siccome ha problemi con possibili implementazioni di T (vedasi Drop trait) - // ho scelto la via più safe anche se può occupare un byte in più di memoria - mem::take(&mut node.element) + Some(Rc::try_unwrap(node).ok().unwrap().into_inner().element) } else { None }