cyclic/
cyclic.rs

1use std::{cell::RefCell, rc::Rc};
2
3use generic_cursors::refcell::RefCellRefMutStack;
4
5#[derive(Debug, Clone)]
6pub struct CyclicDataStructure<T> {
7    data: T,
8    next: Option<Rc<RefCell<Self>>>,
9}
10
11impl<T> CyclicDataStructure<T> {
12    fn next(&mut self) -> Option<&RefCell<Self>> {
13        self.next.as_deref()
14    }
15    fn insert_next(&mut self, new_next: Rc<RefCell<Self>>) -> Option<Rc<RefCell<Self>>> {
16        self.next.replace(new_next)
17    }
18    fn take_next(&mut self) -> Option<Rc<RefCell<Self>>> {
19        self.next.take()
20    }
21}
22
23fn main() {
24    let cycle_a = Rc::new(RefCell::new(CyclicDataStructure {
25        data: 0_u32,
26        next: None,
27    }));
28    let cycle_b = Rc::new(RefCell::new(CyclicDataStructure {
29        data: 1_u32,
30        next: None,
31    }));
32    let cycle_c = Rc::new(RefCell::new(CyclicDataStructure {
33        data: 2_u32,
34        next: None,
35    }));
36
37    cycle_a.borrow_mut().insert_next(cycle_b.clone());
38    cycle_b.borrow_mut().insert_next(cycle_c.clone());
39    cycle_c.borrow_mut().insert_next(cycle_a.clone());
40
41    // Using a MutRefStack to descend *and then ascend* the data structure.
42    // This cannot be done with regular mutable references.
43    let mut stack = RefCellRefMutStack::new(&cycle_a).expect("not mutable borrowed yet");
44    println!("Stack currently at item with value: {}", stack.top().data);
45    loop {
46        if let Err(_borrow_error) = stack
47            .descend_with(CyclicDataStructure::next)
48            .expect("no node has no next")
49        {
50            println!("Found a cycle!");
51            break;
52        }
53        println!("Descended successfully!");
54        println!("Stack currently at item with value: {}", stack.top().data);
55    }
56    println!("Stack currently at item with value: {}", stack.top().data);
57    loop {
58        if let None = stack.ascend() {
59            println!("Reached the head of the linked list!");
60            break;
61        }
62        println!("Ascended successfully!");
63        println!("Stack currently at item with value: {}", stack.top().data);
64    }
65
66    println!("(Breaking the cycle to prevent miri from complaining about memory leaks)");
67    stack.top_mut().take_next();
68}