SinglyEndsMut

Trait SinglyEndsMut 

Source
pub trait SinglyEndsMut<T, M, P>: HasSinglyEndsMut<T, M, P> + SinglyEnds<T, M, P>
where M: MemoryPolicy<Singly<T>>, P: PinnedVec<Node<Singly<T>>>,
{ // Provided methods fn front_mut<'a>(&'a mut self) -> Option<&'a mut T> where M: 'a, P: 'a { ... } fn get_mut<'a>(&'a mut self, idx: &SinglyIdx<T>) -> Option<&'a mut T> where M: 'a, P: 'a { ... } fn try_get_mut<'a>( &'a mut self, idx: &SinglyIdx<T>, ) -> Result<&'a mut T, NodeIdxError> where M: 'a, P: 'a { ... } fn next_mut_of<'a>(&'a mut self, idx: &SinglyIdx<T>) -> Option<&'a mut T> where M: 'a, P: 'a { ... } }
Expand description

A list or view having a single end: front.

Provided Methods§

Source

fn front_mut<'a>(&'a mut self) -> Option<&'a mut T>
where M: 'a, P: 'a,

O(1) Returns a mutable reference to the front of the list, returns None if the list is empty.

§Examples
use orx_linked_list::*;

let mut list = SinglyList::new();

assert!(list.front_mut().is_none());

list.push_front('a');
assert_eq!(Some(&'a'), list.front());

*list.front_mut().unwrap() = 'x';

assert_eq!(Some(&'x'), list.front());
Source

fn get_mut<'a>(&'a mut self, idx: &SinglyIdx<T>) -> Option<&'a mut T>
where M: 'a, P: 'a,

O(1) Returns a mutable reference to the node with the given idx in constant time.

Returns None if the index is invalid.

§Safety

Returns Some if all of the following safety conditions hold:

  • the index is created from this list,
  • the node that this index is created for still belongs to the list (not removed),
  • the node positions in this list are not reorganized to reclaim memory:
    • DoublyList or SinglyList automatically reorganizes nodes on removal of items if the utilization of memory drops below a threshold.
    • DoublyListLazy or SinglyListLazy do not reorganize nodes implicitly, the indices are only invalidated if the reclaim_closed_nodes is manually called.

Returns None otherwise. We can use try_get_mut to understand why the index is invalid.

§Examples

Following example illustrates where automatic reorganization does not happen since no elements are removed from the list.

The indices remain valid.

use orx_linked_list::*;

let mut list = DoublyList::new();

let a = list.push_back('a');
let b = list.push_back('b');

assert_eq!(list.get(&a), Some(&'a'));
assert_eq!(list.get(&b), Some(&'b'));

*list.get_mut(&a).unwrap() = 'x';

list.push_front('c');
list.push_back('d');
list.push_front('e');
let f = list.push_back('f');

assert_eq!(list.get(&a), Some(&'x'));
assert_eq!(list.get(&b), Some(&'b'));
assert_eq!(list.get(&f), Some(&'f'));

let _ = list.pop_back(); // f is removed

*list.get_mut(&a).unwrap() = 'y';

assert_eq!(list.get(&a), Some(&'y'));
assert_eq!(list.get(&b), Some(&'b'));
assert_eq!(list.get(&f), None);

list.clear(); // all removed

assert_eq!(list.get(&a), None);
assert_eq!(list.get(&b), None);
assert_eq!(list.get(&f), None);

In the following, removal of nodes invalidates indices due to reorganization. In these cases, we safely receive None.

Note that, to have complete control on validity of indices, we can use DoublyListLazy or SinglyListLazy. In these variants, indices are invalidated only if we manually call reclaim_closed_nodes.

use orx_linked_list::*;

let mut list = DoublyList::new();

list.push_back('a');
list.push_back('b');
let c = list.push_back('c');
list.push_back('d');
list.push_back('e');

*list.get_mut(&c).unwrap() = 'x';

list.pop_back(); // does not lead to reorganization

assert_eq!(list.get(&c), Some(&'x'));

list.pop_front(); // leads to reorganization

assert_eq!(list.get(&c), None);

In the final example, we attempt to access to a list element using an index created by another list.

use orx_linked_list::*;

let mut list = DoublyList::new();
let idx = list.push_back('a');

let mut other_list = DoublyList::new();
let other_idx = other_list.push_back('a');

assert!(list.get_mut(&idx).is_some());
// assert_eq!(list.get_mut(&other_idx), None);
Source

fn try_get_mut<'a>( &'a mut self, idx: &SinglyIdx<T>, ) -> Result<&'a mut T, NodeIdxError>
where M: 'a, P: 'a,

O(1) Returns a mutable reference to the node with the given idx in constant time.

Returns NodeIdxError if the index is invalid.

§Safety

Returns Some if all of the following safety conditions hold:

  • the index is created from this list,
  • the node that this index is created for still belongs to the list (not removed),
  • the node positions in this list are not reorganized to reclaim memory:
    • DoublyList or SinglyList automatically reorganizes nodes on removal of items if the utilization of memory drops below a threshold.
    • DoublyListLazy or SinglyListLazy do not reorganize nodes implicitly, the indices are only invalidated if the reclaim_closed_nodes is manually called.

Otherwise, returns:

  • RemovedNode if the particular element is removed from the list.
  • OutOfBounds if the index is does not point to the current nodes of the list.
  • ReorganizedCollection if nodes of the list are reorganized to reclaim closed nodes.
§Examples

Following example illustrates where automatic reorganization does not happen since no elements are removed from the list.

The indices remain valid.

use orx_linked_list::*;

let mut list = DoublyList::new();

let a = list.push_back('a');
let b = list.push_back('b');

assert_eq!(list.try_get(&a), Ok(&'a'));
assert_eq!(list.try_get(&b), Ok(&'b'));

*list.try_get_mut(&a).unwrap() = 'x';

list.push_front('c');
list.push_back('d');
list.push_front('e');
let f = list.push_back('f');

assert_eq!(list.try_get(&a), Ok(&'x'));
assert_eq!(list.try_get(&b), Ok(&'b'));
assert_eq!(list.try_get(&f), Ok(&'f'));

let _ = list.pop_back(); // f is removed

*list.try_get_mut(&a).unwrap() = 'y';

assert_eq!(list.try_get(&a), Ok(&'y'));
assert_eq!(list.try_get(&b), Ok(&'b'));
assert_eq!(list.try_get(&f), Err(NodeIdxError::RemovedNode));

list.clear(); // all removed

assert_eq!(list.try_get(&a), Err(NodeIdxError::OutOfBounds));
assert_eq!(list.try_get(&b), Err(NodeIdxError::OutOfBounds));
assert_eq!(list.try_get(&f), Err(NodeIdxError::OutOfBounds));

In the following, removal of nodes invalidates indices due to reorganization. In these cases, we safely receive None.

Note that, to have complete control on validity of indices, we can use DoublyListLazy or SinglyListLazy. In these variants, indices are invalidated only if we manually call reclaim_closed_nodes.

use orx_linked_list::*;

let mut list = DoublyList::new();

list.push_back('a');
list.push_back('b');
let c = list.push_back('c');
list.push_back('d');
list.push_back('e');

*list.try_get_mut(&c).unwrap() = 'x';

list.pop_back(); // does not lead to reorganization

assert_eq!(list.get(&c), Some(&'x'));

list.pop_front(); // leads to reorganization

assert_eq!(list.try_get_mut(&c), Err(NodeIdxError::ReorganizedCollection));

In the final example, we attempt to access to a list element using an index created by another list.

use orx_linked_list::*;

let mut list = DoublyList::new();
let idx = list.push_back('a');

let mut other_list = DoublyList::new();
let other_idx = other_list.push_back('a');

assert!(list.try_get_mut(&idx).is_ok());
// assert_eq!(list.try_get_mut(&other_idx), Err(NodeIdxError::OutOfBounds));
Source

fn next_mut_of<'a>(&'a mut self, idx: &SinglyIdx<T>) -> Option<&'a mut T>
where M: 'a, P: 'a,

O(1) Returns a mutable reference to the element succeeding the one with the given idx. Returns None if the element at idx is the back.

§Panics

Panics if the idx is not valid; i.e., idx_err is not None.

§Examples
use orx_linked_list::*;

let mut list = DoublyList::new();

list.push_front('d');
list.push_front('c');
let b = list.push_front('b');
list.push_front('a');

assert!(list.eq_to_iter_vals(['a', 'b', 'c', 'd']));

let c = list.next_mut_of(&b);
*c.unwrap() = 'x';

assert!(list.eq_to_iter_vals(['a', 'b', 'x', 'd']));

Implementors§

Source§

impl<L, T, M, P> SinglyEndsMut<T, M, P> for L
where L: HasSinglyEndsMut<T, M, P>, M: MemoryPolicy<Singly<T>>, P: PinnedVec<Node<Singly<T>>>,