use crate::*;
pub fn get_current_hook_context() -> HookContext {
unsafe { HookContext::from_inner(CURRENT_HOOK_CONTEXT) }
}
pub fn with_hook_context<F, R>(context: HookContext, f: F) -> R
where
F: FnOnce() -> R,
{
let previous: *mut HookContextInner = unsafe { CURRENT_HOOK_CONTEXT };
unsafe {
CURRENT_HOOK_CONTEXT = context.inner;
}
let result: R = f();
unsafe {
CURRENT_HOOK_CONTEXT = previous;
}
result
}
pub fn create_hook_context() -> HookContext {
let ctx: Box<HookContextInner> = Box::default();
HookContext::from_inner(Box::leak(ctx) as *mut HookContextInner)
}
pub fn use_signal<T, F>(init: F) -> Signal<T>
where
T: Clone + PartialEq + 'static,
F: FnOnce() -> T,
{
let mut ctx: HookContext = get_current_hook_context();
let index: usize = ctx.get_hook_index();
ctx.set_hook_index(index + 1_usize);
if index < ctx.get_hooks().len()
&& let Some(existing) = ctx.get_hooks()[index].downcast_ref::<Signal<T>>()
{
return *existing;
}
let signal: Signal<T> = Signal::new(init());
let cleanup_signal: Signal<T> = signal;
ctx.get_mut_cleanups()
.push(Box::new(move || cleanup_signal.clear_listeners()));
if index < ctx.get_hooks().len() {
ctx.get_mut_hooks()[index] = Box::new(signal);
} else {
ctx.get_mut_hooks().push(Box::new(signal));
}
signal
}