]> git.lizzy.rs Git - rust.git/commitdiff
linked_list: Cleanup code in split_off
authorUlrik Sverdrup <root@localhost>
Sat, 6 Jun 2015 12:26:39 +0000 (14:26 +0200)
committerUlrik Sverdrup <root@localhost>
Sat, 6 Jun 2015 18:05:38 +0000 (20:05 +0200)
src/libcollections/linked_list.rs

index 8fbd45ea770dd209f8c3992c0c98d734ed2db800..721a3a2595e64c670100e5c5a60b7fe32c1bfe0e 100644 (file)
@@ -615,25 +615,29 @@ pub fn split_off(&mut self, at: usize) -> LinkedList<T> {
             iter.tail
         };
 
-        let mut splitted_list = LinkedList {
-            list_head: None,
+        // The split node is the new tail node of the first part and owns
+        // the head of the second part.
+        let mut second_part_head;
+
+        unsafe {
+            second_part_head = split_node.resolve_mut().unwrap().next.take();
+            match second_part_head {
+                None => {}
+                Some(ref mut head) => head.prev = Rawlink::none(),
+            }
+        }
+
+        let second_part = LinkedList {
+            list_head: second_part_head,
             list_tail: self.list_tail,
             length: len - at
         };
 
-        unsafe {
-            // Swap split_node.next with list_head (which is None), nulling out split_node.next,
-            // as it is the new tail.
-            mem::swap(&mut split_node.resolve_mut().unwrap().next, &mut splitted_list.list_head);
-            // Null out list_head.prev. Note this `unwrap` won't fail because if at == len
-            // we already branched out at the top of the fn to return the empty list.
-            splitted_list.list_head.as_mut().unwrap().prev = Rawlink::none();
-        }
-        // Fix the tail ptr
+        // Fix the tail ptr of the first part
         self.list_tail = split_node;
         self.length = at;
 
-        splitted_list
+        second_part
     }
 }
 
@@ -947,7 +951,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 #[cfg(test)]
 mod tests {
     use std::clone::Clone;
-    use std::iter::{Iterator, IntoIterator};
+    use std::iter::{Iterator, IntoIterator, Extend};
     use std::option::Option::{Some, None, self};
     use std::__rand::{thread_rng, Rng};
     use std::thread;
@@ -1115,6 +1119,26 @@ fn test_26021() {
         assert_eq!(v1.iter().collect::<Vec<_>>().len(), 3);
     }
 
+    #[test]
+    fn test_split_off() {
+        let mut v1 = LinkedList::new();
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+
+        // test all splits
+        for ix in 0..1 + v1.len() {
+            let mut a = v1.clone();
+            let b = a.split_off(ix);
+            check_links(&a);
+            check_links(&b);
+            a.extend(b);
+            assert_eq!(v1, a);
+        }
+    }
+
+
     #[cfg(test)]
     fn fuzz_test(sz: i32) {
         let mut m: LinkedList<_> = LinkedList::new();