1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
use crate::{
nodes::index::NodeIndex, selfref_col_mut::into_ref, Node, NodeIndexError, SelfRefCol,
SelfRefColMut, Variant,
};
use orx_split_vec::prelude::PinnedVec;
use std::ops::Deref;
/// Struct allowing to safely, conveniently and efficiently visit nodes of a self referential collection and take `CanLeak` values out.
///
/// # Safety
///
/// This struct holds an immutable reference to the underlying self referential collection.
///
/// This struct cannot be created externally.
/// It is only constructed by `SelfRefCol`s methods such as `visit` and `visit_take` methods.
/// You may find corresponding safety guarantees in the documentation of these methods, which in brief, relies on careful encapsulation
/// preventing any reference to leak into the collection or any node reference to leak out.
pub struct SelfRefColVisit<'rf, 'a, V, T, P>
where
V: Variant<'a, T>,
P: PinnedVec<Node<'a, V, T>>,
'a: 'rf,
{
pub(crate) col: &'rf SelfRefCol<'a, V, T, P>,
}
impl<'rf, 'a, V, T, P> SelfRefColVisit<'rf, 'a, V, T, P>
where
V: Variant<'a, T>,
P: PinnedVec<Node<'a, V, T>>,
{
pub(crate) fn new(vec: &'rf SelfRefCol<'a, V, T, P>) -> Self {
Self { col: vec }
}
// index
/// ***O(1)*** Converts the `node_index` to `Some` of the valid reference to the node in this collection.
///
/// If the node index is invalid, the method returns `None`.
///
/// Note that the validity of the node index can also be queried by `node_index::is_valid_for_collection` method.
///
/// `get_node_ref(collection)` returns `Some` if all of of the following safety and correctness conditions hold:
/// * this index is created from the given `collection`,
/// * the node this index is created for still belongs to the `collection`; i.e., is not removed,
/// * the node positions in the `collection` are not reorganized to reclaim memory.
#[inline(always)]
pub fn get_node_ref(&self, node_index: NodeIndex<'a, V, T>) -> Option<&'a Node<'a, V, T>> {
match node_index.is_valid_for_collection(self.col) {
true => Some(node_index.node_key),
false => None,
}
}
/// ***O(1)*** Converts the `node_index` to a `Ok` of the valid reference to the node in this collection.
///
/// If the node index is invalid, the method returns `Err` of the corresponding `NodeIndexError` depending on the reason of invalidity.
///
/// Note that the corresponding error can also be queried by `node_index::invalidity_reason_for_collection` method.
///
/// `get_node_ref_or_error(collection)` returns `Ok` if all of of the following safety and correctness conditions hold:
/// * this index is created from the given `collection`,
/// * the node this index is created for still belongs to the `collection`; i.e., is not removed,
/// * the node positions in the `collection` are not reorganized to reclaim memory.
#[inline(always)]
pub fn get_node_ref_or_error(
&self,
node_index: NodeIndex<'a, V, T>,
) -> Result<&'a Node<'a, V, T>, NodeIndexError>
where
P: PinnedVec<Node<'a, V, T>>,
{
match node_index.invalidity_reason_for_collection(self.col) {
None => Ok(node_index.node_key),
Some(error) => Err(error),
}
}
/// ***O(1)*** Converts the `node_index` to a reference to the node in this collection.
/// The call panics if `node_index.is_valid_for_collection(collection)` is false; i.e., if this node index is not valid for this collection.
///
/// # Panics
///
/// Panics if the node index is invalid; i.e., if `node_index.is_valid_for_collection` returns false.
///
/// Note that `is_valid_for_collection` returns true if all of of the following safety and correctness conditions hold:
/// * this index is created from the given `collection`,
/// * the node this index is created for still belongs to the `collection`; i.e., is not removed,
/// * the node positions in the `collection` are not reorganized to reclaim memory.
#[inline(always)]
pub fn as_node_ref(&self, node_index: NodeIndex<'a, V, T>) -> &'a Node<'a, V, T> {
assert!(node_index.is_valid_for_collection(self.col));
node_index.node_key
}
// nodes
/// Returns a reference to the first node of the collection.
pub fn first_node<'b>(&self) -> Option<&'b Node<'a, V, T>> {
self.col.pinned_vec.first().map(|x| unsafe { into_ref(x) })
}
/// Returns a reference to the last node of the collection.
pub fn last_node<'b>(&self) -> Option<&'b Node<'a, V, T>> {
self.col.pinned_vec.last().map(|x| unsafe { into_ref(x) })
}
/// Returns a reference to the `at`-th node of the collection.
pub fn get_node<'b>(&self, at: usize) -> Option<&'b Node<'a, V, T>> {
self.col.pinned_vec.get(at).map(|x| unsafe { into_ref(x) })
}
}
impl<'rf, 'a, V, T, P> Deref for SelfRefColVisit<'rf, 'a, V, T, P>
where
V: Variant<'a, T>,
P: PinnedVec<Node<'a, V, T>>,
{
type Target = SelfRefCol<'a, V, T, P>;
fn deref(&self) -> &Self::Target {
self.col
}
}
impl<'rf, 'a, V, T, P> From<&SelfRefColMut<'rf, 'a, V, T, P>> for SelfRefColVisit<'rf, 'a, V, T, P>
where
V: Variant<'a, T>,
P: PinnedVec<Node<'a, V, T>>,
{
fn from(value: &SelfRefColMut<'rf, 'a, V, T, P>) -> Self {
Self::new(unsafe { into_ref(value.col) })
}
}