standard-plugin-sdk 0.1.1

Write Standard Code plugins in Rust: wasm components against standard:plugin@2.0.0
Documentation
//! State that belongs to the component instance: one instance runs on one
//! thread and the host calls one export at a time. On wasm this is a plain
//! static; on other targets (tests with [`crate::testing`]) it is
//! thread-local, so parallel tests never share it.

/// Declares a lazily initialised instance-local value and an accessor
/// `$name(|value: &mut $ty| ...)`.
macro_rules! instance_local {
    ($vis:vis fn $name:ident() -> $ty:ty = $init:expr;) => {
        #[cfg(target_arch = "wasm32")]
        $vis fn $name<R>(f: impl FnOnce(&mut $ty) -> R) -> R {
            struct Slot(core::cell::RefCell<Option<$ty>>);
            // SAFETY: a component instance is single-threaded (see module).
            unsafe impl Sync for Slot {}
            static SLOT: Slot = Slot(core::cell::RefCell::new(None));
            let mut slot = SLOT.0.borrow_mut();
            f(slot.get_or_insert_with(|| $init))
        }

        #[cfg(not(target_arch = "wasm32"))]
        $vis fn $name<R>(f: impl FnOnce(&mut $ty) -> R) -> R {
            std::thread_local! {
                static SLOT: core::cell::RefCell<Option<$ty>> =
                    const { core::cell::RefCell::new(None) };
            }
            SLOT.with(|slot| f(slot.borrow_mut().get_or_insert_with(|| $init)))
        }
    };
}

pub(crate) use instance_local;