use gc_arena::{Arena, Collect, Gc, Mutation, RefLock, Rootable};
#[derive(Copy, Clone, Collect)]
#[collect(no_drop)]
struct Node<'gc, T: 'gc> {
prev: Option<NodePtr<'gc, T>>,
next: Option<NodePtr<'gc, T>>,
value: T,
}
type NodePtr<'gc, T> = Gc<'gc, RefLock<Node<'gc, T>>>;
fn new_node<'gc, T: Collect<'gc>>(mc: &Mutation<'gc>, value: T) -> NodePtr<'gc, T> {
Gc::new(
mc,
RefLock::new(Node {
prev: None,
next: None,
value,
}),
)
}
fn node_join<'gc, T>(mc: &Mutation<'gc>, left: NodePtr<'gc, T>, right: NodePtr<'gc, T>) {
left.borrow_mut(mc).next = Some(right);
right.borrow_mut(mc).prev = Some(left);
}
fn node_rotate_right<'gc, T>(node: &mut NodePtr<'gc, T>) -> bool {
if let Some(next) = node.borrow().next {
*node = next;
true
} else {
false
}
}
fn node_rotate_left<'gc, T>(node: &mut NodePtr<'gc, T>) -> bool {
if let Some(prev) = node.borrow().prev {
*node = prev;
true
} else {
false
}
}
fn main() {
let mut arena = Arena::<Rootable![NodePtr<'_, i32>]>::new(|mc| {
let one = new_node(mc, 1);
let two = new_node(mc, 2);
let three = new_node(mc, 3);
let four = new_node(mc, 4);
node_join(mc, one, two);
node_join(mc, two, three);
node_join(mc, three, four);
one
});
arena.mutate_root(|_, root| {
for i in 1..=4 {
assert_eq!(root.borrow().value, i);
node_rotate_right(root);
}
});
arena.mutate_root(|_, root| {
for i in (1..=4).rev() {
assert_eq!(root.borrow().value, i);
node_rotate_left(root);
}
});
arena.mutate(|mc, root| {
let one = *root;
let two = one.borrow().next.unwrap();
let three = two.borrow().next.unwrap();
node_join(mc, three, one);
});
arena.finish_cycle();
arena.mutate_root(|_, root| {
for _ in 0..2 {
for i in 1..=3 {
assert_eq!(root.borrow().value, i);
node_rotate_right(root);
}
}
});
}