pub use webtau_macros::command;
#[macro_export]
macro_rules! wasm_state {
($T:ty) => {
::std::thread_local! {
static __WEBTAU_STATE: ::std::cell::RefCell<Option<$T>> =
::std::cell::RefCell::new(None);
}
fn set_state(val: $T) {
__WEBTAU_STATE.with(|cell| {
*cell.borrow_mut() = Some(val);
});
}
fn with_state<__F, __R>(f: __F) -> __R
where
__F: FnOnce(&$T) -> __R,
{
__WEBTAU_STATE.with(|cell| {
let borrow = cell.borrow();
let state = borrow
.as_ref()
.expect("webtau: state not initialized — call set_state() first");
f(state)
})
}
fn with_state_mut<__F, __R>(f: __F) -> __R
where
__F: FnOnce(&mut $T) -> __R,
{
__WEBTAU_STATE.with(|cell| {
let mut borrow = cell.borrow_mut();
let state = borrow
.as_mut()
.expect("webtau: state not initialized — call set_state() first");
f(state)
})
}
};
}
#[cfg(test)]
mod tests {
#[derive(Debug, PartialEq)]
struct Counter {
value: i32,
}
wasm_state!(Counter);
#[test]
fn set_and_read_state() {
set_state(Counter { value: 42 });
let result = with_state(|c| c.value);
assert_eq!(result, 42);
}
#[test]
fn mutate_state() {
set_state(Counter { value: 0 });
with_state_mut(|c| c.value += 10);
let result = with_state(|c| c.value);
assert_eq!(result, 10);
}
#[test]
#[should_panic(expected = "state not initialized")]
fn panics_without_init() {
struct Uninitialized;
wasm_state!(Uninitialized);
with_state(|_| {});
}
}