use crate::data::node_data::NodeData;
use crate::variants::variant::Variant;
use crate::{NodeDataLazyClose, NodeRefsArray, NodeRefsVec, SelfRefColMut};
use orx_split_vec::prelude::PinnedVec;
pub struct Node<'a, V, T>
where
V: Variant<'a, T>,
{
pub(crate) data: V::Storage,
pub(crate) prev: V::Prev,
pub(crate) next: V::Next,
}
impl<'a, V, T> Node<'a, V, T>
where
V: Variant<'a, T>,
{
#[inline(always)]
pub fn new_free_node(data: T) -> Self {
Self {
data: V::Storage::active(data),
prev: V::Prev::default(),
next: V::Next::default(),
}
}
#[inline(always)]
pub fn new(data: V::Storage, prev: V::Prev, next: V::Next) -> Self {
Self { data, prev, next }
}
#[inline(always)]
pub fn data(&self) -> Option<&T> {
self.data.get()
}
#[inline(always)]
pub fn prev(&self) -> &V::Prev {
&self.prev
}
#[inline(always)]
pub fn next(&self) -> &V::Next {
&self.next
}
pub fn data_mut(&mut self) -> Option<&mut T> {
self.data.get_mut()
}
#[inline(always)]
pub fn swap_data<'rf, P>(&'a self, vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>, new_value: T) -> T
where
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.swap_data(self, new_value)
}
#[inline(always)]
pub fn set_prev_refs<'rf, P>(&'a self, vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>, prev: V::Prev)
where
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.set_prev_of(self, prev)
}
#[inline(always)]
pub fn set_next_refs<'rf, P>(&'a self, vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>, next: V::Next)
where
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.set_next_of(self, next)
}
#[inline(always)]
pub fn set_next<'rf, P, Next: Into<V::Next>>(
&'a self,
vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>,
next: Next,
) where
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.set_next_of(self, next.into())
}
#[inline(always)]
pub fn set_prev<'rf, P, Prev: Into<V::Prev>>(
&'a self,
vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>,
prev: Prev,
) where
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.set_prev_of(self, prev.into())
}
#[inline(always)]
pub fn clear_next<'rf, P>(&'a self, vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>)
where
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.clear_next_of(self)
}
#[inline(always)]
pub fn clear_prev<'rf, P>(&'a self, vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>)
where
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.clear_prev_of(self)
}
#[inline(always)]
pub fn close_node_take_data<'rf, P>(&'a self, vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>) -> T
where
V: Variant<'a, T, Storage = NodeDataLazyClose<T>>,
P: PinnedVec<Node<'a, V, T>> + 'a,
{
vec_mut.close_node_take_data(self)
}
#[inline(always)]
pub fn close_node_take_data_no_reclaim<'rf, P>(
&'a self,
vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>,
) -> T
where
V: Variant<'a, T, Storage = NodeDataLazyClose<T>>,
P: PinnedVec<Node<'a, V, T>> + 'a,
{
vec_mut.close_node_take_data_no_reclaim(self)
}
#[inline(always)]
pub fn prev_vec_mut<'rf, P>(
&'a self,
vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>,
) -> &mut Vec<&'a Node<'a, V, T>>
where
V: Variant<'a, T, Prev = NodeRefsVec<'a, V, T>>,
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.get_prev_vec_mut(self)
}
#[inline(always)]
pub fn next_vec_mut<'rf, P>(
&'a self,
vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>,
) -> &mut Vec<&'a Node<'a, V, T>>
where
V: Variant<'a, T, Next = NodeRefsVec<'a, V, T>>,
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.get_next_vec_mut(self)
}
#[inline(always)]
pub fn prev_array_mut<'rf, P, const N: usize>(
&'a self,
vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>,
) -> &mut [Option<&'a Node<'a, V, T>>; N]
where
V: Variant<'a, T, Prev = NodeRefsArray<'a, N, V, T>>,
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.get_prev_array_mut(self)
}
#[inline(always)]
pub fn next_array_mut<'rf, P, const N: usize>(
&'a self,
vec_mut: &SelfRefColMut<'rf, 'a, V, T, P>,
) -> &mut [Option<&'a Node<'a, V, T>>; N]
where
V: Variant<'a, T, Next = NodeRefsArray<'a, N, V, T>>,
P: PinnedVec<Node<'a, V, T>>,
{
vec_mut.get_next_array_mut(self)
}
pub(crate) fn ref_eq(&self, other: &Self) -> bool {
let left = self as *const Self;
let right = other as *const Self;
left == right
}
pub(crate) fn ref_eq_to_ptr(&self, other: *const Node<'a, V, T>) -> bool {
let left = self as *const Self;
left == other
}
}
impl<'a, V, T> Clone for Node<'a, V, T>
where
V: Variant<'a, T>,
V::Storage: Clone,
T: Clone,
{
fn clone(&self) -> Self {
Self {
data: self.data.clone(),
prev: Default::default(),
next: Default::default(),
}
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
use crate::{
MemoryReclaimOnThreshold, NodeData, NodeRefSingle, NodeRefs, NodeRefsArray, NodeRefsVec,
SelfRefCol,
};
use orx_split_vec::prelude::PinnedVec;
struct Var;
impl<'a> Variant<'a, char> for Var {
type Storage = NodeDataLazyClose<char>;
type Prev = NodeRefSingle<'a, Self, char>;
type Next = NodeRefsVec<'a, Self, char>;
type Ends = NodeRefsArray<'a, 2, Self, char>;
type MemoryReclaim = MemoryReclaimOnThreshold<2>;
}
#[test]
fn new_free_node() {
let node = Node::<Var, _>::new_free_node('x');
assert!(node.prev().get().is_none());
assert!(node.next().get().is_empty());
assert_eq!(Some(&'x'), node.data());
}
#[test]
fn new() {
let x = Node::<Var, _>::new_free_node('x');
let y = Node::<Var, _>::new_free_node('y');
let node = Node::<Var, _>::new(
NodeDataLazyClose::active('z'),
NodeRefSingle::new(Some(&x)),
NodeRefsVec::new(vec![&y]),
);
assert!(node.prev().get().unwrap().ref_eq(&x));
assert!(node.next().get()[0].ref_eq(&y));
assert_eq!(Some(&'z'), node.data());
}
#[test]
fn data_mut() {
let mut node = Node::<Var, _>::new_free_node('x');
assert_eq!(Some(&'x'), node.data());
*node.data_mut().unwrap() = 'y';
assert_eq!(Some(&'y'), node.data());
}
#[test]
fn swap_data() {
let mut vec = SelfRefCol::<Var, _>::new();
{
let x = SelfRefColMut::new(&mut vec);
let rf = x.push_get_ref('a');
x.set_ends([Some(rf), None]);
}
assert_eq!(vec.pinned_vec.len(), 1);
assert_eq!(vec.pinned_vec.get(0).unwrap().data().unwrap(), &'a');
{
let x = SelfRefColMut::new(&mut vec);
let first = x.ends().get()[0].unwrap();
let old_value = x.swap_data(first, 'z');
assert_eq!('a', old_value);
}
assert_eq!(vec.pinned_vec.len(), 1);
assert_eq!(vec.pinned_vec.get(0).unwrap().data().unwrap(), &'z');
{
let x = SelfRefColMut::new(&mut vec);
let first = x.ends().get()[0].unwrap();
let old_value = first.swap_data(&x, 'o');
assert_eq!('z', old_value);
}
assert_eq!(vec.pinned_vec.len(), 1);
assert_eq!(vec.pinned_vec.get(0).unwrap().data().unwrap(), &'o');
}
#[test]
fn close_node_take_data() {
let mut vec = SelfRefCol::<Var, _>::new();
assert!(vec.pinned_vec.is_empty());
{
let x = SelfRefColMut::new(&mut vec);
let a = x.push_get_ref('a');
assert!(a.is_active());
let val_a = a.close_node_take_data(&x);
assert_eq!('a', val_a);
assert!(a.is_closed());
}
}
#[test]
#[should_panic]
fn close_node_take_data_on_closed_node() {
let mut vec = SelfRefCol::<Var, _>::new();
let x = SelfRefColMut::new(&mut vec);
let a = x.push_get_ref('a');
assert!(a.is_active());
let val_a = a.close_node_take_data(&x);
assert_eq!('a', val_a);
assert!(a.is_closed());
let _ = a.close_node_take_data(&x); }
#[test]
fn set_clear_prev_next_single() {
struct Var;
impl<'a> Variant<'a, char> for Var {
type Storage = NodeDataLazyClose<char>;
type Prev = NodeRefSingle<'a, Self, char>;
type Next = NodeRefSingle<'a, Self, char>;
type Ends = NodeRefsArray<'a, 2, Self, char>;
type MemoryReclaim = MemoryReclaimOnThreshold<2>;
}
let mut vec = SelfRefCol::<Var, _>::new();
assert!(vec.pinned_vec.is_empty());
{
let x = SelfRefColMut::new(&mut vec);
let a = x.push_get_ref('a');
let b = x.push_get_ref('b');
a.set_prev_refs(&x, b.into());
assert!(a.prev().get().unwrap().ref_eq(b));
a.set_prev(&x, b);
assert!(a.prev().get().unwrap().ref_eq(b));
a.set_prev(&x, b);
assert!(a.prev().get().unwrap().ref_eq(b));
a.clear_prev(&x);
assert!(a.prev().get().is_none());
a.set_prev_refs(&x, NodeRefSingle::empty());
assert!(a.prev().get().is_none());
b.set_next(&x, a);
assert!(b.next().get().unwrap().ref_eq(a));
b.set_next(&x, a);
assert!(b.next().get().unwrap().ref_eq(a));
b.clear_next(&x);
assert!(b.next().get().is_none());
a.set_next(&x, b);
b.set_prev(&x, a);
}
let a = &vec.pinned_vec[0];
let b = &vec.pinned_vec[1];
assert!(a.next().get().unwrap().ref_eq(b));
assert!(b.prev().get().unwrap().ref_eq(a));
}
#[test]
fn set_clear_prev_next_vec() {
struct Var;
impl<'a> Variant<'a, char> for Var {
type Storage = NodeDataLazyClose<char>;
type Prev = NodeRefsVec<'a, Self, char>;
type Next = NodeRefsVec<'a, Self, char>;
type Ends = NodeRefsArray<'a, 2, Self, char>;
type MemoryReclaim = MemoryReclaimOnThreshold<2>;
}
let mut vec = SelfRefCol::<Var, _>::new();
assert!(vec.pinned_vec.is_empty());
{
let x = SelfRefColMut::new(&mut vec);
let a = x.push_get_ref('a');
let b = x.push_get_ref('b');
let c = x.push_get_ref('c');
a.set_next_refs(&x, NodeRefsVec::new(vec![b]));
assert_eq!(a.next().get().len(), 1);
assert!(a.next().get().first().unwrap().ref_eq(b));
a.set_next(&x, vec![b]);
assert_eq!(a.next().get().len(), 1);
assert!(a.next().get().first().unwrap().ref_eq(b));
a.next_vec_mut(&x).push(c);
assert_eq!(a.next().get().len(), 2);
assert!(a.next().get().first().unwrap().ref_eq(b));
assert!(a.next().get().get(1).unwrap().ref_eq(c));
a.clear_next(&x);
assert!(a.next().get().is_empty());
a.set_next(&x, NodeRefsVec::empty());
assert!(a.next().get().is_empty());
b.set_prev(&x, vec![a]);
assert_eq!(b.prev().get().len(), 1);
assert!(b.prev().get().first().unwrap().ref_eq(a));
c.set_prev(&x, vec![a, b]);
assert_eq!(c.prev().get().len(), 2);
assert!(c.prev().get().first().unwrap().ref_eq(a));
assert!(c.prev().get().get(1).unwrap().ref_eq(b));
c.prev_vec_mut(&x).remove(0);
assert_eq!(c.prev().get().len(), 1);
assert!(c.prev().get().first().unwrap().ref_eq(b));
c.clear_prev(&x);
assert!(c.prev().get().is_empty());
}
}
#[test]
fn set_clear_prev_next_array() {
struct Var;
impl<'a> Variant<'a, char> for Var {
type Storage = NodeDataLazyClose<char>;
type Prev = NodeRefsArray<'a, 1, Self, char>;
type Next = NodeRefsArray<'a, 2, Self, char>;
type Ends = NodeRefsArray<'a, 2, Self, char>;
type MemoryReclaim = MemoryReclaimOnThreshold<2>;
}
let mut vec = SelfRefCol::<Var, _>::new();
assert!(vec.pinned_vec.is_empty());
{
let x = SelfRefColMut::new(&mut vec);
let a = x.push_get_ref('a');
let b = x.push_get_ref('b');
let c = x.push_get_ref('c');
a.set_next_refs(&x, NodeRefsArray::new([Some(b), Some(c)]));
assert!(a.next().get()[0].unwrap().ref_eq(b));
assert!(a.next().get()[1].unwrap().ref_eq(c));
a.set_next(&x, [Some(b), None]);
assert!(a.next().get()[0].unwrap().ref_eq(b));
assert!(a.next().get()[1].is_none());
a.next_array_mut(&x)[1] = Some(c);
assert!(a.next().get()[1].unwrap().ref_eq(c));
a.clear_next(&x);
assert!(a.next().get()[0].is_none());
assert!(a.next().get()[1].is_none());
a.set_next(&x, NodeRefsArray::empty());
assert!(a.next().get()[0].is_none());
assert!(a.next().get()[1].is_none());
b.set_prev_refs(&x, NodeRefsArray::new([Some(a)]));
assert!(b.prev().get()[0].unwrap().ref_eq(a));
b.prev_array_mut(&x)[0] = None;
assert!(b.prev().get()[0].is_none());
b.set_prev(&x, [Some(c)]);
assert!(b.prev().get()[0].unwrap().ref_eq(c));
b.clear_prev(&x);
assert!(b.prev().get()[0].is_none());
}
}
}