Recursive reference   ![Latest Version] ![Docs version]

This crate provides a way to traverse recursive structures easily and safely. Rust's lifetime rules will usually force you to either only walk forward through the structure, or use recursion, calling your method recursively every time you go down a node, and returning every time you want to go back up, which leads to terrible code.

Instead, you can use the [RecRef] type, to safely and dynamically walk up and down your recursive structure.

documentation crates.io repository

Examples

Say we have a recursive linked list structure


rust enum List<T> { Root(Box<Node<T>>), Empty, } struct Node<T> { value: T, next: List<T>, }

We can use a [RecRef] directly


```rust use recursive_reference::*;

fn main() -> Result<(), ()> { // crate a list to test let node1 = Node { value: 5, next: List::Empty, }; let mut node2 = Node { value: 2, next: List::Root(Box::new(node1)), };

// create a `RecRef`
let mut rec_ref = RecRef::new(&mut node2);
// rec_ref is a smart pointer to the current node
assert_eq!(rec_ref.value, 2);

// move forward through the list
RecRef::extend_result(&mut rec_ref, |node| match &mut node.next {
    List::Root(next_node) => Ok(next_node),
    List::Empty => Err(()),
})?;
assert_eq!(rec_ref.value, 5); // now we're at the second node

// pop the `RecRef`, moving it back to the head
RecRef::pop(&mut rec_ref).ok_or(())?;
assert_eq!(rec_ref.value, 2);
Ok(())

} ```

We can also wrap a [RecRef] in a walker struct


```rust use recursivereference::*; struct Walker<'a, T> { recref: RecRef<'a, Node>, } impl<'a, T> Walker<'a, T> { /// Crates a new Walker pub fn new(node: &'a mut Node) -> Self { Walker { rec_ref: RecRef::new(node), } }

/// Returns `None` when at the tail end of the list.
/// Moves to the next node.
pub fn next(&mut self) -> Option<()> {
    RecRef::extend_result(&mut self.rec_ref, |current| match &mut current.next {
        List::Empty => Err(()),
        List::Root(node) => Ok(node),
    })
    .ok()
}

/// Returns `None` when at the head of the list.
/// Goes back to the previous node.
pub fn prev(&mut self) -> Option<()> {
    RecRef::pop(&mut self.rec_ref)?;
    Some(())
}

/// Returns `None` when at the tail end of the list.
/// Returns `Some(reference)` where `reference` is a mutqable reference to the current value.
pub fn value_mut(&mut self) -> &mut T {
    &mut self.rec_ref.value
}

}

fn main() -> Result<(), ()> { // crate a list to test let node1 = Node { value: 5, next: List::Empty, }; let mut node2 = Node { value: 2, next: List::Root(Box::new(node1)), };

// create a walker for the list
let mut walker = Walker::new(&mut node2);
// walker has mutable access to the node value
assert_eq!(*walker.value_mut(), 2);
// move to the next node
walker.next().ok_or(())?;
assert_eq!(*walker.value_mut(), 5);
assert_eq!(walker.next(), None); // currently at the end of the list
                                 // move back
walker.prev().ok_or(())?;
assert_eq!(*walker.value_mut(), 2);
Ok(())

} `` With a [RecRef`] you can


License

dual licensed with MIT and APACHE 2.0