Skip to main content

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.

The cursor has two special states:

  1. “Before Start”: Positioned before the first element (index() returns None).
  2. “After End”: Positioned after the last element (index() returns None).

§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.

§Example

use pie_core::{ElemPool, PieList};
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
list.push_back(10, &mut pool).unwrap();
list.push_back(20, &mut pool).unwrap();

let mut cursor = list.cursor_mut(&mut pool); // Starts at index 0 (10)

// Move forward
cursor.move_next(&pool);
if let Some(val) = cursor.peek_mut(&mut pool) {
    *val = 99;
}
assert_eq!(cursor.peek(&pool), Some(&99));

// Move backward (supports wrapping from End to Tail, etc)
cursor.move_next(&pool); // Now After End
cursor.move_prev(&pool); // Back to Tail (99)
assert_eq!(cursor.peek(&pool), Some(&99));

list.clear(&mut pool);

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 “Before Start” or “After End”, 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(), 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.

Returns None if the cursor is “Before Start” or “After End”.

§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.

Returns None if the cursor is “Before Start” or “After End”.

§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: &ElemPool<T>)

Moves the cursor to the next element in the list.

  • If “Before Start”: Moves to the first element (Head).
  • If at the last element: Moves to “After End”.
  • If “After End”: Stays at “After End” (no-op).
Source

pub fn move_prev(&mut self, pool: &ElemPool<T>)

Moves the cursor to the previous element in the list.

  • If “After End”: Moves to the last element (Tail).
  • If at the first element: Moves to “Before Start”.
  • If “Before Start”: Stays at “Before Start” (no-op).
Source

pub fn move_to_front(&mut self, pool: &ElemPool<T>)

Moves the cursor to the first element of the list.

If the list is empty, results in “After End” (index 0, len 0).

Source

pub fn move_to_back(&mut self, pool: &ElemPool<T>)

Moves the cursor to the last element of the list.

If the list is empty, results in “After End” (index 0, len 0).

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.

  • If valid position: Inserts before. Cursor points to new element.
  • If “After End”: Appends to list. Cursor points to new element (the new tail).
  • If “Before Start”: Prepends to list. Cursor points to new element (the new head).
§Complexity

O(1)

§Errors

Returns IndexError if the pool fails to allocate a new element.

§Example
// Cursor is at index 0 (value 30)
let mut cursor = list.cursor_mut(&mut pool);

cursor.insert_before(20, &mut pool).unwrap();

// Cursor is now at the new element '20', which is at index 0
assert_eq!(cursor.index(), Some(0));
assert_eq!(*cursor.peek_mut(&mut pool).unwrap(), 20);

let vec: Vec<_> = list.iter(&pool).copied().collect();
assert_eq!(vec, vec![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.

  • If valid position: Inserts after. Cursor stays on current element.
  • If “After End”: No-op logic (Appends? Undefined?). Currently acts like append.
  • If “Before Start”: Prepends to list. Cursor stays “Before Start”.
§Complexity

O(1)

§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]);
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 “After End” position.

§Returns

Some(T) if an element was removed, None if the cursor was not on a valid element (i.e. Before Start or After End).

§Example
// Cursor at index 0 (value 10)
let mut cursor = list.cursor_mut(&mut pool);

let removed = cursor.remove_current(&mut pool);
assert_eq!(removed, Some(10));

// Cursor is now at the next element (20), which shifted to index 0
assert_eq!(cursor.index(), Some(0));
assert_eq!(*cursor.peek_mut(&mut pool).unwrap(), 20);
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.

§Example

let mut front_list;
{
    // Cursor at index 1 (value 20)
    let mut cursor = list.cursor_mut_at(1, &mut pool).unwrap();

    // Split. front_list gets {10}. Original keeps {20}.
    front_list = cursor.split_before(&mut pool).unwrap();

    // Cursor points to 20, which is now index 0 of the truncated list
    assert_eq!(cursor.index(), Some(0));
}

assert_eq!(list.len(), 1);
assert_eq!(front_list.len(), 1);
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.

§Example
let mut list1 = PieList::new(&mut pool);
list1.push_back(30, &mut pool).unwrap();

let mut list2 = PieList::new(&mut pool);
list2.push_back(10, &mut pool).unwrap();
list2.push_back(20, &mut pool).unwrap();

{
    // Cursor at 30
    let mut cursor = list1.cursor_mut(&mut pool);
    cursor.splice_before(&mut list2, &mut pool).unwrap();

    // list1: {10, 20, 30}. Cursor still at 30, now index 2.
    assert_eq!(cursor.index(), Some(2));
}

assert_eq!(list1.len(), 3);
assert!(list2.is_empty());

Trait Implementations§

Source§

impl<'a, T: Debug> Debug for CursorMut<'a, T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

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> UnsafeUnpin for CursorMut<'a, T>

§

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.