From e3c5839159903658a667f789963f20a31567b25c Mon Sep 17 00:00:00 2001 From: Mica White Date: Thu, 30 Jul 2026 07:34:24 -0400 Subject: Initial commit --- src/state.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/state.rs (limited to 'src/state.rs') diff --git a/src/state.rs b/src/state.rs new file mode 100644 index 0000000..8b4de18 --- /dev/null +++ b/src/state.rs @@ -0,0 +1,99 @@ +use core::{ + alloc::Layout, + ops::{Deref, DerefMut}, +}; + +use alloc::alloc::{alloc, dealloc}; +use serde::{Serialize, de::DeserializeOwned}; + +use crate::ScriptContext; + +mod tortuise { + #[link(wasm_import_module = "tortuise")] + unsafe extern "C" { + pub safe fn state_size(context: u64) -> usize; + pub unsafe fn load_state(context: u64, offset: *mut u8); + pub unsafe fn save_state(context: u64, offset: *const u8, size: usize); + + } +} + +impl ScriptContext { + pub fn load_state(&self) -> Option { + unsafe { + let size = tortuise::state_size(self.0); + let layout = Layout::array::(size).unwrap(); + let ptr = alloc(layout); + tortuise::load_state(self.0, ptr); + let data = core::slice::from_raw_parts(ptr, size); + let data = messagepack_serde::from_reader(data).ok()?; + dealloc(ptr, layout); + Some(data) + } + } +} + +fn save_state(context: u64, state: &T) { + unsafe { + let data = messagepack_serde::to_vec(state).unwrap(); + tortuise::save_state(context, data.as_ptr(), data.len()); + } +} + +pub struct StateMut { + context: u64, + data: T, +} + +impl StateMut { + pub fn load(context: &ScriptContext) -> Option { + Some(Self { + context: context.0, + data: context.load_state()?, + }) + } + + pub fn load_or(context: &ScriptContext, default: T) -> Self { + Self { + context: context.0, + data: context.load_state().unwrap_or(default), + } + } + + pub fn load_or_else(context: &ScriptContext, default: impl FnOnce() -> T) -> Self { + Self { + context: context.0, + data: context.load_state().unwrap_or_else(default), + } + } + + pub fn load_or_default(context: &ScriptContext) -> Self + where + T: Default, + { + Self { + context: context.0, + data: context.load_state().unwrap_or_default(), + } + } +} + +impl Deref for StateMut { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.data + } +} + +impl DerefMut for StateMut { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.data + } +} + +impl Drop for StateMut { + fn drop(&mut self) { + save_state(self.context, &self.data); + } +} -- cgit v1.3.1