use crate::tree::{
ChildIterator, ChildIteratorMut, ChildLink, LazyTreeIterator, LazyTreeIteratorMut, Node,
_iter_rec, _iter_rec_mut,
};
use std::{collections::LinkedList, marker::PhantomData, ptr::NonNull};
pub struct Cursor<'a, T> {
pub(crate) current: ChildLink<T>,
pub(crate) _boo: PhantomData<&'a T>,
}
pub struct CursorMut<'a, T> {
pub(crate) current: ChildLink<T>,
pub(crate) _boo: PhantomData<&'a T>,
}
impl<'a, T> Cursor<'a, T> {
pub fn peek(&self) -> &'a T {
unsafe { &(*self.current.as_ptr()).elem }
}
pub fn peek_child(&self, index: usize) -> &'a T {
if index >= self.childs_len() {
panic!(
"Tried to peek child on child {} but current has only {} childs",
index,
self.childs_len()
);
}
unsafe { &(*(*self.current.as_ptr()).childs[index].as_ptr()).elem }
}
pub fn navigate_to(&mut self, index: usize) {
if index >= self.childs_len() {
panic!(
"Tried to navigate to child {} but current has only {} childs",
index,
self.childs_len()
);
}
unsafe {
self.current = (*self.current.as_ptr()).childs[index];
}
}
pub fn ascend(&mut self) {
if !self.has_father() {
panic!("Tried to call ascend but current has no father");
}
unsafe {
self.current = (*self.current.as_ptr()).father.unwrap();
}
}
pub fn has_father(&self) -> bool {
unsafe { (*self.current.as_ptr()).father.is_some() }
}
pub fn childs_len(&self) -> usize {
unsafe { (*self.current.as_ptr()).childs.len() }
}
pub fn iter_childs(&self) -> ChildIterator<'a, T> {
ChildIterator {
current: self.current,
i: 0,
len: self.childs_len(),
_boo: PhantomData,
}
}
pub fn iter(&self) -> impl Iterator<Item = &'a T> {
let mut container = Vec::new();
_iter_rec(self.current, &mut container);
container.into_iter()
}
pub fn lazyiter(&self) -> LazyTreeIterator<'a, T> {
let mut idx_list = LinkedList::new();
idx_list.push_back(0);
LazyTreeIterator {
cursor: Cursor {
current: self.current,
_boo: PhantomData,
},
idx_list,
_boo: PhantomData,
}
}
}
impl<'a, T> CursorMut<'a, T> {
pub fn peek(&self) -> &'a T {
unsafe { &(*self.current.as_ptr()).elem }
}
pub fn peek_mut(&mut self) -> &mut T {
unsafe { &mut (*self.current.as_ptr()).elem }
}
pub fn peek_child(&self, index: usize) -> &'a T {
if index >= self.childs_len() {
panic!(
"Tried to peek child on child {} but current has only {} childs",
index,
self.childs_len()
);
}
unsafe { &(*(*self.current.as_ptr()).childs[index].as_ptr()).elem }
}
pub fn peek_child_mut(&mut self, index: usize) -> &mut T {
if index >= self.childs_len() {
panic!(
"Tried to peek child on child {} but current has only {} childs",
index,
self.childs_len()
);
}
unsafe { &mut (*(*self.current.as_ptr()).childs[index].as_ptr()).elem }
}
pub fn navigate_to(&mut self, index: usize) {
if index >= self.childs_len() {
panic!(
"Tried to navigate to child {} but current has only {} childs",
index,
self.childs_len()
);
}
unsafe {
self.current = (*self.current.as_ptr()).childs[index];
}
}
pub fn ascend(&mut self) {
if !self.has_father() {
panic!("Tried to call ascend but current has no father");
}
unsafe {
self.current = (*self.current.as_ptr()).father.unwrap();
}
}
pub fn has_father(&self) -> bool {
unsafe { (*self.current.as_ptr()).father.is_some() }
}
pub fn childs_len(&self) -> usize {
unsafe { (*self.current.as_ptr()).childs.len() }
}
pub fn iter_childs(&self) -> ChildIterator<'a, T> {
ChildIterator {
current: self.current,
i: 0,
len: self.childs_len(),
_boo: PhantomData,
}
}
pub fn iter_childs_mut(&self) -> ChildIteratorMut<'a, T> {
ChildIteratorMut {
current: self.current,
i: 0,
len: self.childs_len(),
_boo: PhantomData,
}
}
pub fn iter(&self) -> impl Iterator<Item = &'a T> {
let mut container = Vec::new();
_iter_rec(self.current, &mut container);
container.into_iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &'a mut T> {
let mut container = Vec::new();
_iter_rec_mut(self.current, &mut container);
container.into_iter()
}
pub fn lazyiter(&self) -> LazyTreeIterator<'a, T> {
let mut idx_list = LinkedList::new();
idx_list.push_back(0);
LazyTreeIterator {
cursor: Cursor {
current: self.current,
_boo: PhantomData,
},
idx_list,
_boo: PhantomData,
}
}
pub fn lazyiter_mut(&mut self) -> LazyTreeIteratorMut<'a, T> {
let mut idx_list = LinkedList::new();
idx_list.push_back(0);
LazyTreeIteratorMut {
cursor: UnsafeCursor {
current: self.current,
_boo: PhantomData,
},
idx_list,
_boo: PhantomData,
}
}
pub fn push(&mut self, el: T) {
unsafe {
let current_node = &mut *(self.current.as_ptr());
current_node
.childs
.push(NonNull::new_unchecked(Box::into_raw(Box::new(Node {
elem: el,
childs: Vec::new(),
father: Some(self.current),
}))))
}
}
pub fn push_iter<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
{
for el in iter.into_iter() {
self.push(el);
}
}
}
pub struct UnsafeCursor<'a, T> {
pub(crate) current: ChildLink<T>,
pub(crate) _boo: PhantomData<&'a T>,
}
impl<'a, T> UnsafeCursor<'a, T> {
pub fn peek(&self) -> &'a T {
unsafe { &(*self.current.as_ptr()).elem }
}
pub unsafe fn peek_mut(&self) -> &'a mut T {
unsafe { &mut (*self.current.as_ptr()).elem }
}
pub fn peek_child(&self, index: usize) -> &'a T {
if index >= self.childs_len() {
panic!(
"Tried to peek child on child {} but current has only {} childs",
index,
self.childs_len()
);
}
unsafe { &(*(*self.current.as_ptr()).childs[index].as_ptr()).elem }
}
pub unsafe fn peek_child_mut(&self, index: usize) -> &'a mut T {
if index >= self.childs_len() {
panic!(
"Tried to call peek_child_mut on child {} but current has only {} childs",
index,
self.childs_len()
);
}
unsafe { &mut (*(*self.current.as_ptr()).childs[index].as_ptr()).elem }
}
pub fn navigate_to(&mut self, index: usize) {
if index >= self.childs_len() {
panic!(
"Tried to navigate to child {} but current has only {} childs",
index,
self.childs_len()
);
}
unsafe {
self.current = (*self.current.as_ptr()).childs[index];
}
}
pub fn ascend(&mut self) {
if !self.has_father() {
panic!("Tried to call ascend but current has no father");
}
unsafe {
self.current = (*self.current.as_ptr()).father.unwrap();
}
}
pub fn has_father(&self) -> bool {
unsafe { (*self.current.as_ptr()).father.is_some() }
}
pub fn childs_len(&self) -> usize {
unsafe { (*self.current.as_ptr()).childs.len() }
}
pub fn iter_childs(&self) -> ChildIterator<'a, T> {
ChildIterator {
current: self.current,
i: 0,
len: self.childs_len(),
_boo: PhantomData,
}
}
pub fn push(&mut self, el: T) {
unsafe {
let current_node = &mut *(self.current.as_ptr());
current_node
.childs
.push(NonNull::new_unchecked(Box::into_raw(Box::new(Node {
elem: el,
childs: Vec::new(),
father: Some(self.current),
}))))
}
}
pub fn push_iter<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
{
for el in iter.into_iter() {
self.push(el);
}
}
}
#[cfg(test)]
mod test {
use super::super::Tree;
#[test]
fn unsafe_cursor1() {
let mut tree = Tree::from_element(0);
tree.push_iter(vec![1, 2, 3]);
tree.navigate_to(1);
tree.push_iter(vec![9, 8]);
tree.ascend();
tree.navigate_to(0);
tree.push_iter(vec![9, 10]);
tree.navigate_to(0);
tree.push(15);
tree.go_to_root();
let mut cursor1 = tree.unsafe_cursor();
cursor1.navigate_to(0);
let mut cursor2 = tree.unsafe_cursor();
cursor2.navigate_to(1);
cursor2.navigate_to(1);
unsafe { *cursor1.peek_mut() += 1 };
unsafe { *cursor2.peek_mut() += 2 };
assert_eq!(
tree.lazyiter().collect::<Vec<&i32>>(),
vec![&0, &2, &9, &15, &10, &2, &9, &10, &3]
);
unsafe { *cursor1.peek_mut() -= 10 };
assert_eq!(
tree.lazyiter().collect::<Vec<&i32>>(),
vec![&0, &-8, &9, &15, &10, &2, &9, &10, &3]
);
}
#[test]
fn unsafe_cursor2() {
let mut tree = Tree::from_element(vec![1, 2, 3]);
tree.push_iter(vec![vec![4], vec![5, 6, 7, 8]]);
let mut cursor1 = tree.unsafe_cursor();
cursor1.navigate_to(0);
let mut cursor2 = tree.unsafe_cursor();
cursor2.navigate_to(1);
unsafe { cursor2.peek_mut().push(9) };
unsafe { cursor1.peek_mut().pop() };
assert_eq!(
tree.iter().collect::<Vec<&Vec<i32>>>(),
vec![&vec![1, 2, 3], &vec![], &vec![5, 6, 7, 8, 9]]
);
unsafe {
let vec = cursor2.peek_mut();
while !vec.is_empty() {
vec.pop();
}
}
assert_eq!(
tree.iter().collect::<Vec<&Vec<i32>>>(),
vec![&vec![1, 2, 3], &vec![], &vec![]]
);
cursor2.push(vec![10]);
assert_eq!(
tree.iter().collect::<Vec<&Vec<i32>>>(),
vec![&vec![1, 2, 3], &vec![], &vec![], &vec![10]]
)
}
}