state-macro 0.1.1

Syntax sugar for stateful functions
Documentation
use state_macro::stateful_expr;
use std::cell::RefCell;
use std::rc::Rc;

type State = Rc<RefCell<u8>>;

fn inc(state: State) -> u8 {
    let mut i = state.borrow_mut();
    *i += 1;
    *i
}

fn dec(state: State) -> u8 {
    let mut i = state.borrow_mut();
    *i = i.saturating_sub(1);
    *i
}

fn add(state: State, value: u8) -> u8 {
    let mut i = state.borrow_mut();
    *i += value;
    *i
}

// Test basic stateful_expr functionality
#[stateful_expr(State, state.clone())]
fn test_basic() -> u8 {
    ::inc() + ::inc()
}

#[test]
fn test_basic_stateful_expr() {
    let state = Rc::new(RefCell::new(0u8));
    let result = test_basic(state.clone());

    // Should increment twice: 0 -> 1 -> 2, then return 1 + 2 = 3
    assert_eq!(result, 3);
    assert_eq!(*state.borrow(), 2);
}

// Test with more complex expressions
#[stateful_expr(State, state.clone())]
fn test_complex_expr(multiplier: u8) -> u8 {
    (::inc() * multiplier) + ::dec()
}

#[test]
fn test_complex_stateful_expr() {
    let state = Rc::new(RefCell::new(5u8));
    let result = test_complex_expr(state.clone(), 3);

    // Initial state: 5
    // inc() -> 6, multiply by 3 -> 18
    // dec() -> 5
    // Result: 18 + 5 = 23
    assert_eq!(result, 23);
    assert_eq!(*state.borrow(), 5);
}

// Module for testing namespaced functions with stateful_expr
mod operations {
    use super::*;

    #[stateful_expr(State, state.clone())]
    pub fn increment_and_add(value: u8) -> u8 {
        ::inc() + ::add(value)
    }
}

#[test]
fn test_stateful_expr_with_namespaced_functions() {
    let state = Rc::new(RefCell::new(10u8));
    let result = operations::increment_and_add(state.clone(), 5);

    // Initial: 10
    // inc() -> 11
    // add(5) -> 16
    // Result: 11 + 16 = 27
    assert_eq!(result, 27);
    assert_eq!(*state.borrow(), 16);
}

// Test with conditional expressions
#[stateful_expr(State, state.clone())]
fn test_conditional(threshold: u8) -> u8 {
    if ::inc() > threshold {
        ::add(10)
    } else {
        ::add(1)
    }
}

#[test]
fn test_stateful_expr_with_conditionals() {
    let state1 = Rc::new(RefCell::new(0u8));
    let result1 = test_conditional(state1.clone(), 5);

    // inc() -> 1, which is <= 5, so add(1) -> 2
    assert_eq!(result1, 2);
    assert_eq!(*state1.borrow(), 2);

    let state2 = Rc::new(RefCell::new(8u8));
    let result2 = test_conditional(state2.clone(), 5);

    // inc() -> 9, which is > 5, so add(10) -> 19
    assert_eq!(result2, 19);
    assert_eq!(*state2.borrow(), 19);
}

// Test with block expressions
#[stateful_expr(State, state.clone())]
fn test_block_expr() -> u8 {
    ({
        let first = ::inc();
        let second = ::inc();
        first * second
    }) + ::dec()
}

#[test]
fn test_stateful_expr_with_blocks() {
    let state = Rc::new(RefCell::new(2u8));
    let result = test_block_expr(state.clone());

    // Initial: 2
    // Block: inc() -> 3, inc() -> 4, 3 * 4 = 12
    // dec() -> 3
    // Result: 12 + 3 = 15
    assert_eq!(result, 15);
    assert_eq!(*state.borrow(), 3);
}