Skip to main content

Crate kevy_lua_host

Crate kevy_lua_host 

Expand description

Scoped-borrow bridge between kevy_lua::Bridge and a host-owned mutable shard state (Store, KeyspaceStore, anything 'static).

kevy-lua’s dispatch closure type is Fn(&[&[u8]], bool) -> Vec<u8> + 'static. The 'static bound is mandatory — luna stores the closure as Vm userdata (Any + 'static). That makes it impossible to capture &mut T directly. This crate offers a tiny LuaHost<T> wrapper that re-introduces the borrow via a scoped thread-local pointer set inside LuaHost::eval and cleared right after. The dispatch closure consults the pointer.

§Safety contract (read this if you touch the unsafe)

  • LuaHost<T> parameterises over the host context type T (kevy’s Store for the production wiring; an arbitrary type in tests).
  • LuaHost::new(dispatch_fn) builds a kevy-lua Bridge whose dispatch closure does with_current::<T>(|t| dispatch_fn(t, argv, ro)). The closure carries NO captured state of its own — it just reads the scoped pointer.
  • LuaHost::eval(&mut self, &mut T, …) (and friends) set CURRENT_T = ctx as *mut T BEFORE delegating to Bridge::eval, and CLEAR CURRENT_T = null after. A Drop guard ensures the clear even on panic.
  • Inside the dispatch closure, with_current dereferences CURRENT_T exactly once per call. The pointer is only ever non-null while the outer &mut T is borrowed mutably by LuaHost::eval, so no aliasing exists.
  • kevy is single-threaded per-shard — every shard owns its own LuaHost<T> and runs on a dedicated thread. The thread-local gives correct isolation without any synchronisation overhead.

The unsafe footprint is one unsafe { &mut *p } inside with_current plus the Cell::set(ptr) ergonomics. Audited per every kevy v1.27+ commit touching this file.

Structs§

LuaHost
kevy-side per-shard Lua host. Wraps a kevy_lua::Bridge plus the scoped-pointer plumbing.

Functions§

with_current
Run f with a mutable borrow of the currently-set host context. Returns None if LuaHost::eval isn’t on the stack.