decursion 0.1.0

Write recursive algorithms without worrying about stack overflows
Documentation
use decursion::*;

#[derive(Default)]
struct Tree {
    children: Vec<Tree>,
}

fn recursive_total_nodes(mut tree: Tree) -> usize {
    let mut result = 1;
    for child in std::mem::take(&mut tree.children) {
        result += recursive_total_nodes(child);
    }
    result
}

const N: usize = 1_000_000;
fn construct_tree() -> Tree {
    let mut tree = Tree::default();
    for _ in 0..N {
        tree = Tree {
            children: vec![tree, Tree::default()],
        };
    }
    tree
}

#[test]
#[ignore = "this test stack overflows"]
fn test_overflow() {
    let tree = construct_tree();
    assert_eq!(recursive_total_nodes(tree), N * 2 + 1);
}

async fn total_nodes(mut tree: Tree) -> usize {
    let mut result = 1;
    for child in std::mem::take(&mut tree.children) {
        result += total_nodes(child).decurse().await;
    }
    result
}

#[test]
fn test_decursed() {
    let tree = construct_tree();
    assert_eq!(run_decursing(total_nodes(tree)), N * 2 + 1);
}

impl Drop for Tree {
    fn drop(&mut self) {
        if self.children.is_empty() {
            return;
        }
        async fn safe_drop(mut tree: Tree) {
            for child in std::mem::take(&mut tree.children) {
                safe_drop(child).decurse().await;
            }
        }
        run_decursing(safe_drop(std::mem::take(self)));
    }
}