pub struct CursorMut<'a, T> { /* private fields */ }Expand description
A cursor with mutable access to a PieList.
A CursorMut provides a flexible way to inspect and modify a PieList
at a specific location. It holds a mutable reference to its PieList,
which means that while the cursor exists, the list cannot be modified by
any other means.
§Rationale
The cursor pattern is essential for implementing complex list operations
efficiently, such as split_before or splice_before. It avoids the need
for repeated index-based lookups from the beginning or end of the list.
A key feature of this design is that the ElemPool is only borrowed by
individual methods of the cursor, not by the CursorMut struct itself. This
allows multiple independent cursors to exist and operate on different lists
within the same pool concurrently.
Implementations§
Source§impl<'a, T> CursorMut<'a, T>
impl<'a, T> CursorMut<'a, T>
Sourcepub fn index(&self) -> Option<usize>
pub fn index(&self) -> Option<usize>
Returns the logical index of the cursor’s current position.
The index is 0-based. If the cursor is pointing “past the end” of the
list (i.e., at the sentinel node), this method returns None.
§Example
let mut cursor = list.cursor_mut(&mut pool);
assert_eq!(cursor.index(), Some(0));
cursor.move_next(&mut pool);
assert_eq!(cursor.index(), Some(1));
cursor.move_next(&mut pool);
assert_eq!(cursor.index(), None); // Past the endSourcepub fn peek<'p>(&self, pool: &'p ElemPool<T>) -> Option<&'p T>
pub fn peek<'p>(&self, pool: &'p ElemPool<T>) -> Option<&'p T>
Provides a reference to the element at the cursor’s current position.
If the cursor is not pointing at a valid element (e.g., it’s past the end),
this returns None.
§Example
let mut cursor = list.cursor_mut(&mut pool);
assert_eq!(cursor.peek(&pool), Some(&10));Sourcepub fn peek_mut<'p>(&mut self, pool: &'p mut ElemPool<T>) -> Option<&'p mut T>
pub fn peek_mut<'p>(&mut self, pool: &'p mut ElemPool<T>) -> Option<&'p mut T>
Provides a mutable reference to the element at the cursor’s current position.
If the cursor is not pointing at a valid element (e.g., it’s past the end),
this returns None.
§Example
let mut cursor = list.cursor_mut(&mut pool);
if let Some(value) = cursor.peek_mut(&mut pool) {
*value = 99;
}
assert_eq!(list.front(&pool), Some(&99));Sourcepub fn move_next(&mut self, pool: &mut ElemPool<T>)
pub fn move_next(&mut self, pool: &mut ElemPool<T>)
Moves the cursor to the next element in the list.
If the cursor is already past the end of the list, this has no effect.
Sourcepub fn move_prev(&mut self, pool: &mut ElemPool<T>)
pub fn move_prev(&mut self, pool: &mut ElemPool<T>)
Moves the cursor to the previous element in the list.
If the cursor is at the beginning of the list, it will move to a position “before the start” (the sentinel), and its logical index will become 0. If it is already “past the end”, this method has no effect.
Sourcepub fn insert_before(
&mut self,
data: T,
pool: &mut ElemPool<T>,
) -> Result<(), IndexError>
pub fn insert_before( &mut self, data: T, pool: &mut ElemPool<T>, ) -> Result<(), IndexError>
Inserts a new element before the cursor’s current position.
After insertion, the cursor will point to the newly inserted element.
§Rationale
This behavior is consistent with Rust’s standard library LinkedList::CursorMut
and is useful for building up a sequence at a specific point.
§Complexity
O(1)
§Errors
Returns IndexError if the pool fails to allocate a new element.
§Example
// Cursor is at index 1 (value 30)
let mut cursor = list.cursor_mut_at(1, &mut pool).unwrap();
cursor.insert_before(20, &mut pool).unwrap();
// Cursor is now at the new element '20', which is at index 1
assert_eq!(cursor.index(), Some(1));
assert_eq!(*cursor.peek_mut(&mut pool).unwrap(), 20);
let vec: Vec<_> = list.iter(&pool).copied().collect();
assert_eq!(vec, vec![10, 20, 30]);Sourcepub fn insert_after(
&mut self,
data: T,
pool: &mut ElemPool<T>,
) -> Result<(), IndexError>
pub fn insert_after( &mut self, data: T, pool: &mut ElemPool<T>, ) -> Result<(), IndexError>
Inserts a new element after the cursor’s current position.
The cursor’s position does not change.
§Rationale
This is useful for appending elements after a specific point without losing the current position.
§Complexity
O(1)
§Errors
Returns IndexError if the pool fails to allocate a new element.
§Example
// Cursor is at index 0 (value 10)
let mut cursor = list.cursor_mut(&mut pool);
cursor.insert_after(20, &mut pool).unwrap();
// Cursor is still at index 0 (value 10)
assert_eq!(cursor.index(), Some(0));
assert_eq!(*cursor.peek_mut(&mut pool).unwrap(), 10);
let vec: Vec<_> = list.iter(&pool).copied().collect();
assert_eq!(vec, vec![10, 20, 30]);Sourcepub fn remove_current(&mut self, pool: &mut ElemPool<T>) -> Option<T>
pub fn remove_current(&mut self, pool: &mut ElemPool<T>) -> Option<T>
Removes the element at the cursor’s current position and returns its data.
After removal, the cursor moves to the next element. If the removed element was the last one, the cursor moves to the “past the end” position.
§Rationale
Moving to the next element is a common pattern when draining or filtering a list, making it convenient.
§Complexity
O(1)
§Returns
Some(T) if an element was removed, None if the cursor was not on a
valid element.
§Example
// Cursor at index 1 (value 20)
let mut cursor = list.cursor_mut_at(1, &mut pool).unwrap();
let removed = cursor.remove_current(&mut pool);
assert_eq!(removed, Some(20));
// Cursor is now at the next element (30), which is now at index 1
assert_eq!(cursor.index(), Some(1));
assert_eq!(*cursor.peek_mut(&mut pool).unwrap(), 30);Sourcepub fn split_before(
&mut self,
pool: &mut ElemPool<T>,
) -> Result<PieList<T>, IndexError>
pub fn split_before( &mut self, pool: &mut ElemPool<T>, ) -> Result<PieList<T>, IndexError>
Splits the list into two at the cursor’s current position.
The original list (self) is modified to contain all elements from the
current position onwards. A new PieList is returned containing all
elements before the current position.
After the split, the cursor remains on the same element, which is now the first element of the original list. Its logical index becomes 0.
§Complexity
O(1)
§Example
let front_list;
{
// Cursor at index 2 (value 30)
let mut cursor = list.cursor_mut_at(2, &mut pool).unwrap();
// Split the list. `front_list` will get elements {10, 20}.
front_list = cursor.split_before(&mut pool).unwrap();
// The cursor is now at the beginning of the modified original list.
assert_eq!(cursor.index(), Some(0));
assert_eq!(*cursor.peek_mut(&mut pool).unwrap(), 30);
} // cursor is dropped here, releasing the mutable borrow on `list`.
// The original list now contains {30, 40}.
assert_eq!(list.len(), 2);
assert_eq!(list.front(&pool), Some(&30));
// The new list contains the elements before the split point.
assert_eq!(front_list.len(), 2);
assert_eq!(front_list.front(&pool), Some(&10));Sourcepub fn splice_before(
&mut self,
other: &mut PieList<T>,
pool: &mut ElemPool<T>,
) -> Result<(), IndexError>
pub fn splice_before( &mut self, other: &mut PieList<T>, pool: &mut ElemPool<T>, ) -> Result<(), IndexError>
Moves all elements from other into self’s list, inserting them
just before the cursor’s current position.
After the operation, other is left empty. The cursor’s position does
not change, but its logical index is updated to reflect the newly
inserted elements.
§Rationale
This is a highly efficient way to merge two lists without iterating or reallocating elements. It only requires a few pointer updates.
§Complexity
O(1)
§Example
let mut list1 = PieList::new(&mut pool);
list1.push_back(10, &mut pool).unwrap();
list1.push_back(40, &mut pool).unwrap();
let mut list2 = PieList::new(&mut pool);
list2.push_back(20, &mut pool).unwrap();
list2.push_back(30, &mut pool).unwrap();
{
// Cursor at index 1 (value 40) in list1
let mut cursor = list1.cursor_mut_at(1, &mut pool).unwrap();
cursor.splice_before(&mut list2, &mut pool).unwrap();
// Cursor still points to 40, but its logical index is now 3
assert_eq!(cursor.index(), Some(3));
} // cursor is dropped here, releasing the mutable borrow on `list1`.
assert!(list2.is_empty());
assert_eq!(list1.len(), 4);
let vec: Vec<_> = list1.iter(&pool).copied().collect();
assert_eq!(vec, vec![10, 20, 30, 40]);