X-Git-Url: https://git.ralfj.de/rust-101.git/blobdiff_plain/a2eeb1b93e8f52b2119fb11d56f5ffc764ac747b..53ea4d72d5db48b56a9cb81397c7302653c74d0b:/workspace/src/part16.rs?ds=sidebyside diff --git a/workspace/src/part16.rs b/workspace/src/part16.rs index a804f8e..fa5b184 100644 --- a/workspace/src/part16.rs +++ b/workspace/src/part16.rs @@ -1,5 +1,5 @@ -// Rust-101, Part 16: Unsafe, Drop (WIP) -// =============================== +// Rust-101, Part 16: Unsafe Rust, Drop +// ==================================== use std::ptr; use std::mem; @@ -12,7 +12,7 @@ struct Node { prev: NodePtr, data: T, } -// A node pointer is a *mutable raw point* to a node. +// A node pointer is a *mutable raw pointer* to a node. type NodePtr = *mut Node; // The linked list itself stores pointers to the first and the last node. In addition, we tell Rust that this type @@ -37,12 +37,12 @@ impl LinkedList { LinkedList { first: ptr::null_mut(), last: ptr::null_mut(), _marker: PhantomData } } - // Add a new node to the end of the list. + // This function adds a new node to the end of the list. pub fn push_back(&mut self, t: T) { // Create the new node, and make it a raw pointer. let new = Box::new( Node { data: t, next: ptr::null_mut(), prev: self.last } ); let new = box_into_raw(new); - // Update other points to this node. + // Update other pointers to this node. if self.last.is_null() { debug_assert!(self.first.is_null()); // The list is currently empty, so we have to update the head pointer. @@ -60,12 +60,13 @@ impl LinkedList { // Add testcases for `push_back` and all of your functions. The `pop` functions should take `&mut self` // and return `Option`. - // Of course, we will also want to provide an iterator. - pub fn iter_mut(&self) -> IterMut { + // Next, we are going to provide an iterator. + pub fn iter_mut(&mut self) -> IterMut { IterMut { next: self.first, _marker: PhantomData } } } + pub struct IterMut<'a, T> where T: 'a { next: NodePtr, _marker: PhantomData<&'a mut LinkedList>, @@ -77,26 +78,26 @@ impl<'a, T> Iterator for IterMut<'a, T> { fn next(&mut self) -> Option { // The actual iteration is straight-forward: Once we reached a null pointer, we are done. if self.next.is_null() { - None + None } else { - // Otherwise, we can convert the next pointer to a borrow, get a borrow to the data + // Otherwise, we can convert the next pointer to a reference, get a reference to the data // and update the iterator. let next = unsafe { &mut *self.next }; let ret = &mut next.data; - self.next = next.next; - Some(ret) + unimplemented!() } } } -// **Exercise 16.2**: Add a method `iter` and a type `Iter` providing iteration for shared borrows. +// **Exercise 16.2**: Add a method `iter` and a type `Iter` providing iteration for shared references. // Add testcases for both kinds of iterators. // ## `Drop` + impl Drop for LinkedList { // The destructor itself is a method which takes `self` in mutably borrowed form. It cannot own `self`, because then - // the destructor of `self` would be called at the end pf the function, resulting in endless recursion... + // the destructor of `self` would be called at the end of the function, resulting in endless recursion. fn drop(&mut self) { let mut cur_ptr = self.first; while !cur_ptr.is_null() { @@ -110,4 +111,5 @@ impl Drop for LinkedList { } } +// ## The End