CursorMut

Struct CursorMut 

Source
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>

Source

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 end
Source

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));
Source

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));
Source

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.

Source

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.

Source

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]);
Source

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]);
Source

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);
Source

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));
Source

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]);

Auto Trait Implementations§

§

impl<'a, T> Freeze for CursorMut<'a, T>

§

impl<'a, T> RefUnwindSafe for CursorMut<'a, T>
where T: RefUnwindSafe,

§

impl<'a, T> Send for CursorMut<'a, T>
where T: Send,

§

impl<'a, T> Sync for CursorMut<'a, T>
where T: Sync,

§

impl<'a, T> Unpin for CursorMut<'a, T>
where T: Unpin,

§

impl<'a, T> !UnwindSafe for CursorMut<'a, T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.