decurse 0.0.4

Macro to make recursive function run on the heap (i.e. no stack overflow).
Documentation
use std::{cell::RefCell, rc::Rc};

use decurse::decurse;

#[test]
fn test_factorial() {
	#[decurse]
	fn factorial(x: u32) -> u32 {
		if x == 0 {
			1
		} else {
			x * factorial(x - 1)
		}
	}
	assert_eq!(factorial(6), 720);
}

#[test]
fn test_fibonacci() {
	#[decurse]
	fn fibonacci(x: u32) -> u32 {
		if x == 0 || x == 1 {
			1
		} else {
			fibonacci(x - 1) + fibonacci(x - 2)
		}
	}
	assert_eq!(fibonacci(10), 89);
}

#[test]
fn test_no_return() {
	#[decurse]
	fn no_return(modify_me: Rc<RefCell<String>>, iter: u32) {
		if iter == 0 {
		} else {
			modify_me.borrow_mut().push_str(&format!("{}, ", iter));
			no_return(modify_me, iter - 1);
		}
	}
	let cell = RefCell::new(String::new());
	let rc = Rc::new(cell);
	no_return(rc.clone(), 5);
	assert_eq!(*(rc.borrow()), "5, 4, 3, 2, 1, ");
}

#[test]
fn test_no_arg() {
	thread_local! {
		static CHANGE_ME: RefCell<usize> = RefCell::new(0);
	};

	#[decurse]
	fn no_arg() {
		if CHANGE_ME.with(|f: &RefCell<usize>| {
			let mut bm = f.borrow_mut();
			if *bm == 5 {
				false
			} else {
				*bm += 1;
				true
			}
		}) {
			no_arg();
		}
	}

	CHANGE_ME.with(|f| {
		*f.borrow_mut() = 0;
	});
	no_arg();
	CHANGE_ME.with(|f| {
		assert_eq!(*f.borrow(), 5);
	});
}

#[test]
fn test_generic() {
	#[decurse]
	fn recursive<T: std::ops::Sub<i32, Output = T> + std::cmp::PartialEq + 'static>(
		value: T,
		until: T,
	) -> T {
		if value == until {
			value
		} else {
			recursive::<T>(value - 1, until)
		}
	}
	assert_eq!(recursive(5, 0), 0);
}