about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorCharles Lew <crlf0710@gmail.com>2020-01-14 20:02:27 +0800
committerCharles Lew <crlf0710@gmail.com>2020-01-14 20:11:52 +0800
commit06b9a73cfa5ef1cb6fb9160d61f1beada2b81b79 (patch)
tree80d26af9673daaae5f92263e0b5e8732e5813c49 /src/liballoc
parentd2c509a3c6b06ba02807bf94c00fad4c4a9262a5 (diff)
downloadrust-06b9a73cfa5ef1cb6fb9160d61f1beada2b81b79.tar.gz
rust-06b9a73cfa5ef1cb6fb9160d61f1beada2b81b79.zip
Update APIs according to RFC change suggestions.
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/collections/linked_list.rs43
-rw-r--r--src/liballoc/collections/linked_list/tests.rs60
2 files changed, 85 insertions, 18 deletions
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index d7504b0b80b..b88ca8a0fb0 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -509,20 +509,42 @@ impl<T> LinkedList<T> {
         IterMut { head: self.head, tail: self.tail, len: self.len, list: self }
     }
 
-    /// Provides a cursor.
+    /// Provides a cursor at the front element.
+    ///
+    /// The cursor is pointing to the "ghost" non-element if the list is empty.
     #[inline]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
-    pub fn cursor(&self) -> Cursor<'_, T> {
+    pub fn cursor_front(&self) -> Cursor<'_, T> {
         Cursor { index: 0, current: self.head, list: self }
     }
 
-    /// Provides a cursor with editing operations.
+    /// Provides a cursor with editing operations at the front element.
+    ///
+    /// The cursor is pointing to the "ghost" non-element if the list is empty.
     #[inline]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
-    pub fn cursor_mut(&mut self) -> CursorMut<'_, T> {
+    pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> {
         CursorMut { index: 0, current: self.head, list: self }
     }
 
+    /// Provides a cursor at the back element.
+    ///
+    /// The cursor is pointing to the "ghost" non-element if the list is empty.
+    #[inline]
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn cursor_back(&self) -> Cursor<'_, T> {
+        Cursor { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self }
+    }
+
+    /// Provides a cursor with editing operations at the back element.
+    ///
+    /// The cursor is pointing to the "ghost" non-element if the list is empty.
+    #[inline]
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> {
+        CursorMut { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self }
+    }
+
     /// Returns `true` if the `LinkedList` is empty.
     ///
     /// This operation should compute in O(1) time.
@@ -1146,8 +1168,6 @@ impl<T: fmt::Debug> fmt::Debug for Cursor<'_, T> {
 /// Cursors always rest between two elements in the list, and index in a logically circular way.
 /// To accommodate this, there is a "ghost" non-element that yields `None` between the head and
 /// tail of the list.
-///
-/// When created, cursors start at the front of the list, or the "ghost" non-element if the list is empty.
 #[unstable(feature = "linked_list_cursors", issue = "58533")]
 pub struct CursorMut<'a, T: 'a> {
     index: usize,
@@ -1474,9 +1494,12 @@ impl<'a, T> CursorMut<'a, T> {
     /// If the cursor is pointing at the "ghost" non-element then the entire contents
     /// of the `LinkedList` are moved.
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
-    pub fn split_after(self) -> LinkedList<T> {
+    pub fn split_after(&mut self) -> LinkedList<T> {
         let split_off_idx = if self.index == self.list.len { 0 } else { self.index + 1 };
-        // no need to update `self.index` because the cursor is consumed.
+        if self.index == self.list.len {
+            // The "ghost" non-element's index has changed to 0.
+            self.index = 0;
+        }
         unsafe { self.list.split_off_after_node(self.current, split_off_idx) }
     }
 
@@ -1487,9 +1510,9 @@ impl<'a, T> CursorMut<'a, T> {
     /// If the cursor is pointing at the "ghost" non-element then the entire contents
     /// of the `LinkedList` are moved.
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
-    pub fn split_before(self) -> LinkedList<T> {
+    pub fn split_before(&mut self) -> LinkedList<T> {
         let split_off_idx = self.index;
-        // no need to update `self.index` because the cursor is consumed.
+        self.index = 0;
         unsafe { self.list.split_off_before_node(self.current, split_off_idx) }
     }
 }
diff --git a/src/liballoc/collections/linked_list/tests.rs b/src/liballoc/collections/linked_list/tests.rs
index d223752c7f7..085f734ed91 100644
--- a/src/liballoc/collections/linked_list/tests.rs
+++ b/src/liballoc/collections/linked_list/tests.rs
@@ -309,7 +309,7 @@ fn drain_to_empty_test() {
 fn test_cursor_move_peek() {
     let mut m: LinkedList<u32> = LinkedList::new();
     m.extend(&[1, 2, 3, 4, 5, 6]);
-    let mut cursor = m.cursor();
+    let mut cursor = m.cursor_front();
     assert_eq!(cursor.current(), Some(&1));
     assert_eq!(cursor.peek_next(), Some(&2));
     assert_eq!(cursor.peek_prev(), None);
@@ -326,9 +326,26 @@ fn test_cursor_move_peek() {
     assert_eq!(cursor.peek_prev(), Some(&1));
     assert_eq!(cursor.index(), Some(1));
 
+    let mut cursor = m.cursor_back();
+    assert_eq!(cursor.current(), Some(&6));
+    assert_eq!(cursor.peek_next(), None);
+    assert_eq!(cursor.peek_prev(), Some(&5));
+    assert_eq!(cursor.index(), Some(5));
+    cursor.move_next();
+    assert_eq!(cursor.current(), None);
+    assert_eq!(cursor.peek_next(), Some(&1));
+    assert_eq!(cursor.peek_prev(), Some(&6));
+    assert_eq!(cursor.index(), None);
+    cursor.move_prev();
+    cursor.move_prev();
+    assert_eq!(cursor.current(), Some(&5));
+    assert_eq!(cursor.peek_next(), Some(&6));
+    assert_eq!(cursor.peek_prev(), Some(&4));
+    assert_eq!(cursor.index(), Some(4));
+
     let mut m: LinkedList<u32> = LinkedList::new();
     m.extend(&[1, 2, 3, 4, 5, 6]);
-    let mut cursor = m.cursor_mut();
+    let mut cursor = m.cursor_front_mut();
     assert_eq!(cursor.current(), Some(&mut 1));
     assert_eq!(cursor.peek_next(), Some(&mut 2));
     assert_eq!(cursor.peek_prev(), None);
@@ -352,24 +369,51 @@ fn test_cursor_move_peek() {
     assert_eq!(cursor2.index(), Some(2));
     assert_eq!(cursor.current(), Some(&mut 2));
     assert_eq!(cursor.index(), Some(1));
+
+    let mut m: LinkedList<u32> = LinkedList::new();
+    m.extend(&[1, 2, 3, 4, 5, 6]);
+    let mut cursor = m.cursor_back_mut();
+    assert_eq!(cursor.current(), Some(&mut 6));
+    assert_eq!(cursor.peek_next(), None);
+    assert_eq!(cursor.peek_prev(), Some(&mut 5));
+    assert_eq!(cursor.index(), Some(5));
+    cursor.move_next();
+    assert_eq!(cursor.current(), None);
+    assert_eq!(cursor.peek_next(), Some(&mut 1));
+    assert_eq!(cursor.peek_prev(), Some(&mut 6));
+    assert_eq!(cursor.index(), None);
+    cursor.move_prev();
+    cursor.move_prev();
+    assert_eq!(cursor.current(), Some(&mut 5));
+    assert_eq!(cursor.peek_next(), Some(&mut 6));
+    assert_eq!(cursor.peek_prev(), Some(&mut 4));
+    assert_eq!(cursor.index(), Some(4));
+    let mut cursor2 = cursor.as_cursor();
+    assert_eq!(cursor2.current(), Some(&5));
+    assert_eq!(cursor2.index(), Some(4));
+    cursor2.move_prev();
+    assert_eq!(cursor2.current(), Some(&4));
+    assert_eq!(cursor2.index(), Some(3));
+    assert_eq!(cursor.current(), Some(&mut 5));
+    assert_eq!(cursor.index(), Some(4));
 }
 
 #[test]
 fn test_cursor_mut_insert() {
     let mut m: LinkedList<u32> = LinkedList::new();
     m.extend(&[1, 2, 3, 4, 5, 6]);
-    let mut cursor = m.cursor_mut();
+    let mut cursor = m.cursor_front_mut();
     cursor.insert_before(7);
     cursor.insert_after(8);
     check_links(&m);
     assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[7, 1, 8, 2, 3, 4, 5, 6]);
-    let mut cursor = m.cursor_mut();
+    let mut cursor = m.cursor_front_mut();
     cursor.move_prev();
     cursor.insert_before(9);
     cursor.insert_after(10);
     check_links(&m);
     assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[10, 7, 1, 8, 2, 3, 4, 5, 6, 9]);
-    let mut cursor = m.cursor_mut();
+    let mut cursor = m.cursor_front_mut();
     cursor.move_prev();
     assert_eq!(cursor.remove_current(), None);
     cursor.move_next();
@@ -383,7 +427,7 @@ fn test_cursor_mut_insert() {
     assert_eq!(cursor.remove_current(), Some(10));
     check_links(&m);
     assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[1, 8, 2, 3, 4, 5, 6]);
-    let mut cursor = m.cursor_mut();
+    let mut cursor = m.cursor_front_mut();
     let mut p: LinkedList<u32> = LinkedList::new();
     p.extend(&[100, 101, 102, 103]);
     let mut q: LinkedList<u32> = LinkedList::new();
@@ -395,12 +439,12 @@ fn test_cursor_mut_insert() {
         m.iter().cloned().collect::<Vec<_>>(),
         &[200, 201, 202, 203, 1, 100, 101, 102, 103, 8, 2, 3, 4, 5, 6]
     );
-    let mut cursor = m.cursor_mut();
+    let mut cursor = m.cursor_front_mut();
     cursor.move_prev();
     let tmp = cursor.split_before();
     assert_eq!(m.into_iter().collect::<Vec<_>>(), &[]);
     m = tmp;
-    let mut cursor = m.cursor_mut();
+    let mut cursor = m.cursor_front_mut();
     cursor.move_next();
     cursor.move_next();
     cursor.move_next();