mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-16 14:07:04 +00:00
Implement Cursor for linked lists. (RFC 2570).
This commit is contained in:
parent
88d1109600
commit
d59e9b40a3
@ -242,6 +242,88 @@ impl<T> LinkedList<T> {
|
||||
|
||||
self.len -= 1;
|
||||
}
|
||||
|
||||
/// Splices a series of nodes between two existing nodes.
|
||||
///
|
||||
/// Warning: this will not check that the provided node belongs to the two existing lists.
|
||||
#[inline]
|
||||
unsafe fn splice_nodes(
|
||||
&mut self,
|
||||
existing_prev: Option<NonNull<Node<T>>>,
|
||||
existing_next: Option<NonNull<Node<T>>>,
|
||||
splice_start: NonNull<Node<T>>,
|
||||
splice_end: NonNull<Node<T>>,
|
||||
splice_length: usize,
|
||||
) {
|
||||
// This method takes care not to create multiple mutable references to whole nodes at the same time,
|
||||
// to maintain validity of aliasing pointers into `element`.
|
||||
if let Some(mut existing_prev) = existing_prev {
|
||||
existing_prev.as_mut().next = Some(splice_start);
|
||||
} else {
|
||||
self.head = Some(splice_start);
|
||||
}
|
||||
if let Some(mut existing_next) = existing_next {
|
||||
existing_next.as_mut().prev = Some(splice_end);
|
||||
} else {
|
||||
self.tail = Some(splice_end);
|
||||
}
|
||||
let mut splice_start = splice_start;
|
||||
splice_start.as_mut().prev = existing_prev;
|
||||
let mut splice_end = splice_end;
|
||||
splice_end.as_mut().next = existing_next;
|
||||
|
||||
self.len += splice_length;
|
||||
}
|
||||
|
||||
/// Detaches all nodes from a linked list as a series of nodes.
|
||||
#[inline]
|
||||
fn detach_all_nodes(mut self) -> Option<(NonNull<Node<T>>, NonNull<Node<T>>, usize)> {
|
||||
let head = self.head.take();
|
||||
let tail = self.tail.take();
|
||||
let len = mem::replace(&mut self.len, 0);
|
||||
if let Some(head) = head {
|
||||
let tail = tail.unwrap_or_else(|| unsafe { core::hint::unreachable_unchecked() });
|
||||
Some((head, tail, len))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn split_off_after_node(
|
||||
&mut self,
|
||||
split_node: Option<NonNull<Node<T>>>,
|
||||
at: usize,
|
||||
) -> Self {
|
||||
// The split node is the new tail node of the first part and owns
|
||||
// the head of the second part.
|
||||
if let Some(mut split_node) = split_node {
|
||||
let second_part_head;
|
||||
let second_part_tail;
|
||||
second_part_head = split_node.as_mut().next.take();
|
||||
if let Some(mut head) = second_part_head {
|
||||
head.as_mut().prev = None;
|
||||
second_part_tail = self.tail;
|
||||
} else {
|
||||
second_part_tail = None;
|
||||
}
|
||||
|
||||
let second_part = LinkedList {
|
||||
head: second_part_head,
|
||||
tail: second_part_tail,
|
||||
len: self.len - at,
|
||||
marker: PhantomData,
|
||||
};
|
||||
|
||||
// Fix the tail ptr of the first part
|
||||
self.tail = Some(split_node);
|
||||
self.len = at;
|
||||
|
||||
second_part
|
||||
} else {
|
||||
mem::replace(self, LinkedList::new())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -319,6 +401,27 @@ impl<T> LinkedList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Moves all elements from `other` to the begin of the list.
|
||||
#[unstable(feature = "linked_list_prepend", issue = "none")]
|
||||
pub fn prepend(&mut self, other: &mut Self) {
|
||||
match self.head {
|
||||
None => mem::swap(self, other),
|
||||
Some(mut head) => {
|
||||
// `as_mut` is okay here because we have exclusive access to the entirety
|
||||
// of both lists.
|
||||
if let Some(mut other_tail) = other.tail.take() {
|
||||
unsafe {
|
||||
head.as_mut().prev = Some(other_tail);
|
||||
other_tail.as_mut().next = Some(head);
|
||||
}
|
||||
|
||||
self.head = other.head.take();
|
||||
self.len += mem::replace(&mut other.len, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides a forward iterator.
|
||||
///
|
||||
/// # Examples
|
||||
@ -373,6 +476,20 @@ impl<T> LinkedList<T> {
|
||||
IterMut { head: self.head, tail: self.tail, len: self.len, list: self }
|
||||
}
|
||||
|
||||
/// Provides a cursor.
|
||||
#[inline]
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn cursor(&self) -> Cursor<'_, T> {
|
||||
Cursor { index: 0, current: self.head, list: self }
|
||||
}
|
||||
|
||||
/// Provides a cursor with editing operations.
|
||||
#[inline]
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn cursor_mut(&mut self) -> CursorMut<'_, T> {
|
||||
CursorMut { index: 0, current: self.head, list: self }
|
||||
}
|
||||
|
||||
/// Returns `true` if the `LinkedList` is empty.
|
||||
///
|
||||
/// This operation should compute in O(1) time.
|
||||
@ -703,30 +820,7 @@ impl<T> LinkedList<T> {
|
||||
}
|
||||
iter.tail
|
||||
};
|
||||
|
||||
// The split node is the new tail node of the first part and owns
|
||||
// the head of the second part.
|
||||
let second_part_head;
|
||||
|
||||
unsafe {
|
||||
second_part_head = split_node.unwrap().as_mut().next.take();
|
||||
if let Some(mut head) = second_part_head {
|
||||
head.as_mut().prev = None;
|
||||
}
|
||||
}
|
||||
|
||||
let second_part = LinkedList {
|
||||
head: second_part_head,
|
||||
tail: self.tail,
|
||||
len: len - at,
|
||||
marker: PhantomData,
|
||||
};
|
||||
|
||||
// Fix the tail ptr of the first part
|
||||
self.tail = split_node;
|
||||
self.len = at;
|
||||
|
||||
second_part
|
||||
unsafe { self.split_off_after_node(split_node, at) }
|
||||
}
|
||||
|
||||
/// Creates an iterator which uses a closure to determine if an element should be removed.
|
||||
@ -986,6 +1080,321 @@ impl<T> IterMut<'_, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A cursor over a `LinkedList`.
|
||||
///
|
||||
/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can
|
||||
/// safely mutate the list during iteration. This is because the lifetime of its yielded
|
||||
/// references is tied to its own lifetime, instead of just the underlying list. This means
|
||||
/// cursors cannot yield multiple elements at once.
|
||||
///
|
||||
/// 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 element if the list is empty.
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub struct Cursor<'a, T: 'a> {
|
||||
index: usize,
|
||||
current: Option<NonNull<Node<T>>>,
|
||||
list: &'a LinkedList<T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Cursor<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Cursor").field(&self.list).field(&self.index).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A cursor over a `LinkedList` with editing operations.
|
||||
///
|
||||
/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can
|
||||
/// safely mutate the list during iteration. This is because the lifetime of its yielded
|
||||
/// references is tied to its own lifetime, instead of just the underlying list. This means
|
||||
/// cursors cannot yield multiple elements at once.
|
||||
///
|
||||
/// 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 element if the list is empty.
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub struct CursorMut<'a, T: 'a> {
|
||||
index: usize,
|
||||
current: Option<NonNull<Node<T>>>,
|
||||
list: &'a mut LinkedList<T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
impl<T: fmt::Debug> fmt::Debug for CursorMut<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("CursorMut").field(&self.list).field(&self.index).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Cursor<'a, T> {
|
||||
/// Move to the subsequent element of the list if it exists or the empty
|
||||
/// element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn move_next(&mut self) {
|
||||
match self.current.take() {
|
||||
// We had no current element; the cursor was sitting at the start position
|
||||
// Next element should be the head of the list
|
||||
None => {
|
||||
self.current = self.list.head;
|
||||
self.index = 0;
|
||||
}
|
||||
// We had a previous element, so let's go to its next
|
||||
Some(current) => unsafe {
|
||||
self.current = current.as_ref().next;
|
||||
self.index += 1;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Move to the previous element of the list
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn move_prev(&mut self) {
|
||||
match self.current.take() {
|
||||
// No current. We're at the start of the list. Yield None and jump to the end.
|
||||
None => {
|
||||
self.current = self.list.tail;
|
||||
self.index = self.list.len().checked_sub(1).unwrap_or(0);
|
||||
}
|
||||
// Have a prev. Yield it and go to the previous element.
|
||||
Some(current) => unsafe {
|
||||
self.current = current.as_ref().prev;
|
||||
self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn current(&self) -> Option<&'a T> {
|
||||
unsafe { self.current.map(|current| &(*current.as_ptr()).element) }
|
||||
}
|
||||
|
||||
/// Get the next element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn peek_next(&self) -> Option<&'a T> {
|
||||
unsafe {
|
||||
let next = match self.current {
|
||||
None => self.list.head,
|
||||
Some(current) => current.as_ref().next,
|
||||
};
|
||||
next.map(|next| &(*next.as_ptr()).element)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the previous element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn peek_prev(&self) -> Option<&'a T> {
|
||||
unsafe {
|
||||
let prev = match self.current {
|
||||
None => self.list.tail,
|
||||
Some(current) => current.as_ref().prev,
|
||||
};
|
||||
prev.map(|prev| &(*prev.as_ptr()).element)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> CursorMut<'a, T> {
|
||||
/// Move to the subsequent element of the list if it exists or the empty
|
||||
/// element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn move_next(&mut self) {
|
||||
match self.current.take() {
|
||||
// We had no current element; the cursor was sitting at the start position
|
||||
// Next element should be the head of the list
|
||||
None => {
|
||||
self.current = self.list.head;
|
||||
self.index = 0;
|
||||
}
|
||||
// We had a previous element, so let's go to its next
|
||||
Some(current) => unsafe {
|
||||
self.current = current.as_ref().next;
|
||||
self.index += 1;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Move to the previous element of the list
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn move_prev(&mut self) {
|
||||
match self.current.take() {
|
||||
// No current. We're at the start of the list. Yield None and jump to the end.
|
||||
None => {
|
||||
self.current = self.list.tail;
|
||||
self.index = self.list.len().checked_sub(1).unwrap_or(0);
|
||||
}
|
||||
// Have a prev. Yield it and go to the previous element.
|
||||
Some(current) => unsafe {
|
||||
self.current = current.as_ref().prev;
|
||||
self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn current(&mut self) -> Option<&mut T> {
|
||||
unsafe { self.current.map(|current| &mut (*current.as_ptr()).element) }
|
||||
}
|
||||
|
||||
/// Get the next element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn peek_next(&mut self) -> Option<&mut T> {
|
||||
unsafe {
|
||||
let next = match self.current {
|
||||
None => self.list.head,
|
||||
Some(current) => current.as_ref().next,
|
||||
};
|
||||
next.map(|next| &mut (*next.as_ptr()).element)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the previous element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn peek_prev(&mut self) -> Option<&mut T> {
|
||||
unsafe {
|
||||
let prev = match self.current {
|
||||
None => self.list.tail,
|
||||
Some(current) => current.as_ref().prev,
|
||||
};
|
||||
prev.map(|prev| &mut (*prev.as_ptr()).element)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an immutable cursor at the current element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T> {
|
||||
Cursor { list: self.list, current: self.current, index: self.index }
|
||||
}
|
||||
}
|
||||
|
||||
// Now the list editing operations
|
||||
|
||||
impl<'a, T> CursorMut<'a, T> {
|
||||
/// Insert `item` after the cursor
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn insert_after(&mut self, item: T) {
|
||||
unsafe {
|
||||
let spliced_node = Box::into_raw_non_null(Box::new(Node::new(item)));
|
||||
let (node, node_next) = match self.current {
|
||||
None => (None, self.list.head),
|
||||
Some(node) => {
|
||||
let node_next = node.as_ref().next;
|
||||
(Some(node), node_next)
|
||||
}
|
||||
};
|
||||
self.list.splice_nodes(node, node_next, spliced_node, spliced_node, 1);
|
||||
if self.current.is_none() {
|
||||
// The ghost element's index has increased by 1.
|
||||
self.index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert `item` before the cursor
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn insert_before(&mut self, item: T) {
|
||||
unsafe {
|
||||
let spliced_node = Box::into_raw_non_null(Box::new(Node::new(item)));
|
||||
let (node_prev, node) = match self.current {
|
||||
None => (self.list.tail, None),
|
||||
Some(node) => {
|
||||
let node_prev = node.as_ref().prev;
|
||||
(node_prev, Some(node))
|
||||
}
|
||||
};
|
||||
self.list.splice_nodes(node_prev, node, spliced_node, spliced_node, 1);
|
||||
self.index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove and return the current item, moving the cursor to the next item
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn remove(&mut self) -> Option<T> {
|
||||
let unlinked_node = self.current?;
|
||||
unsafe {
|
||||
self.current = unlinked_node.as_ref().next;
|
||||
self.list.unlink_node(unlinked_node);
|
||||
let unlinked_node = Box::from_raw(unlinked_node.as_ptr());
|
||||
Some((*unlinked_node).element)
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert `list` between the current element and the next
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn splice_after(&mut self, list: LinkedList<T>) {
|
||||
unsafe {
|
||||
let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() {
|
||||
Some(parts) => parts,
|
||||
_ => return,
|
||||
};
|
||||
let (node, node_next) = match self.current {
|
||||
None => (None, self.list.head),
|
||||
Some(node) => {
|
||||
let node_next = node.as_ref().next;
|
||||
(Some(node), node_next)
|
||||
}
|
||||
};
|
||||
self.list.splice_nodes(node, node_next, splice_head, splice_tail, splice_len);
|
||||
if self.current.is_none() {
|
||||
// The ghost element's index has increased by `splice_len`.
|
||||
self.index += splice_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert `list` between the previous element and current
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn splice_before(&mut self, list: LinkedList<T>) {
|
||||
unsafe {
|
||||
let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() {
|
||||
Some(parts) => parts,
|
||||
_ => return,
|
||||
};
|
||||
let (node_prev, node) = match self.current {
|
||||
None => (self.list.tail, None),
|
||||
Some(node) => {
|
||||
let node_prev = node.as_ref().prev;
|
||||
(node_prev, Some(node))
|
||||
}
|
||||
};
|
||||
self.list.splice_nodes(node_prev, node, splice_head, splice_tail, splice_len);
|
||||
self.index += splice_len;
|
||||
}
|
||||
}
|
||||
|
||||
/// Split the list in two after the current element
|
||||
/// The returned list consists of all elements following the current one.
|
||||
// note: consuming the cursor is not necessary here, but it makes sense
|
||||
// given the interface
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn split_after(self) -> LinkedList<T> {
|
||||
let split_off_idx = if self.index == self.list.len { 0 } else { self.index + 1 };
|
||||
unsafe {
|
||||
let split_off_node = self.current;
|
||||
self.list.split_off_after_node(split_off_node, split_off_idx)
|
||||
}
|
||||
}
|
||||
/// Split the list in two before the current element
|
||||
#[unstable(feature = "linked_list_cursors", issue = "58533")]
|
||||
pub fn split_before(self) -> LinkedList<T> {
|
||||
let split_off_idx = self.index;
|
||||
unsafe {
|
||||
let split_off_node = match self.current {
|
||||
Some(node) => node.as_ref().prev,
|
||||
None => self.list.tail,
|
||||
};
|
||||
self.list.split_off_after_node(split_off_node, split_off_idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator produced by calling `drain_filter` on LinkedList.
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
pub struct DrainFilter<'a, T: 'a, F: 'a>
|
||||
|
@ -304,3 +304,101 @@ fn drain_to_empty_test() {
|
||||
assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(m.into_iter().collect::<Vec<_>>(), &[]);
|
||||
}
|
||||
|
||||
#[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();
|
||||
assert_eq!(cursor.current(), Some(&1));
|
||||
assert_eq!(cursor.peek_next(), Some(&2));
|
||||
assert_eq!(cursor.peek_prev(), None);
|
||||
cursor.move_prev();
|
||||
assert_eq!(cursor.current(), None);
|
||||
assert_eq!(cursor.peek_next(), Some(&1));
|
||||
assert_eq!(cursor.peek_prev(), Some(&6));
|
||||
cursor.move_next();
|
||||
cursor.move_next();
|
||||
assert_eq!(cursor.current(), Some(&2));
|
||||
assert_eq!(cursor.peek_next(), Some(&3));
|
||||
assert_eq!(cursor.peek_prev(), Some(&1));
|
||||
|
||||
let mut m: LinkedList<u32> = LinkedList::new();
|
||||
m.extend(&[1, 2, 3, 4, 5, 6]);
|
||||
let mut cursor = m.cursor_mut();
|
||||
assert_eq!(cursor.current(), Some(&mut 1));
|
||||
assert_eq!(cursor.peek_next(), Some(&mut 2));
|
||||
assert_eq!(cursor.peek_prev(), None);
|
||||
cursor.move_prev();
|
||||
assert_eq!(cursor.current(), None);
|
||||
assert_eq!(cursor.peek_next(), Some(&mut 1));
|
||||
assert_eq!(cursor.peek_prev(), Some(&mut 6));
|
||||
cursor.move_next();
|
||||
cursor.move_next();
|
||||
assert_eq!(cursor.current(), Some(&mut 2));
|
||||
assert_eq!(cursor.peek_next(), Some(&mut 3));
|
||||
assert_eq!(cursor.peek_prev(), Some(&mut 1));
|
||||
let mut cursor2 = cursor.as_cursor();
|
||||
assert_eq!(cursor2.current(), Some(&2));
|
||||
cursor2.move_next();
|
||||
assert_eq!(cursor2.current(), Some(&3));
|
||||
assert_eq!(cursor.current(), Some(&mut 2));
|
||||
}
|
||||
|
||||
#[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();
|
||||
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();
|
||||
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();
|
||||
cursor.move_prev();
|
||||
assert_eq!(cursor.remove(), None);
|
||||
cursor.move_next();
|
||||
cursor.move_next();
|
||||
assert_eq!(cursor.remove(), Some(7));
|
||||
cursor.move_prev();
|
||||
cursor.move_prev();
|
||||
cursor.move_prev();
|
||||
assert_eq!(cursor.remove(), Some(9));
|
||||
cursor.move_next();
|
||||
assert_eq!(cursor.remove(), 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 p: LinkedList<u32> = LinkedList::new();
|
||||
p.extend(&[100, 101, 102, 103]);
|
||||
let mut q: LinkedList<u32> = LinkedList::new();
|
||||
q.extend(&[200, 201, 202, 203]);
|
||||
cursor.splice_after(p);
|
||||
cursor.splice_before(q);
|
||||
check_links(&m);
|
||||
assert_eq!(
|
||||
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();
|
||||
cursor.move_prev();
|
||||
let tmp = cursor.split_before();
|
||||
assert_eq!(tmp.into_iter().collect::<Vec<_>>(), &[]);
|
||||
let mut cursor = m.cursor_mut();
|
||||
cursor.move_next();
|
||||
cursor.move_next();
|
||||
cursor.move_next();
|
||||
cursor.move_next();
|
||||
cursor.move_next();
|
||||
cursor.move_next();
|
||||
let tmp = cursor.split_after();
|
||||
assert_eq!(tmp.into_iter().collect::<Vec<_>>(), &[102, 103, 8, 2, 3, 4, 5, 6]);
|
||||
check_links(&m);
|
||||
assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[200, 201, 202, 203, 1, 100, 101]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user