From ec40f6e3acc7874b82709ab81b254c741529fdff Mon Sep 17 00:00:00 2001 From: Mica White Date: Mon, 26 Oct 2026 10:52:04 -0400 Subject: Finish engine --- src/allocator.rs | 204 ----------------------------------------------- src/buffer.rs | 235 ------------------------------------------------------- src/entity.rs | 133 ------------------------------- src/input.rs | 84 -------------------- src/lib.rs | 31 +------- src/log.rs | 36 --------- src/process.rs | 14 ---- src/random.rs | 73 ----------------- src/scene.rs | 32 -------- src/script.rs | 44 ----------- src/state.rs | 99 ----------------------- src/storage.rs | 84 -------------------- src/time.rs | 142 --------------------------------- 13 files changed, 3 insertions(+), 1208 deletions(-) delete mode 100644 src/allocator.rs delete mode 100644 src/buffer.rs delete mode 100644 src/entity.rs delete mode 100644 src/input.rs delete mode 100644 src/log.rs delete mode 100644 src/process.rs delete mode 100644 src/random.rs delete mode 100644 src/scene.rs delete mode 100644 src/script.rs delete mode 100644 src/state.rs delete mode 100644 src/storage.rs delete mode 100644 src/time.rs (limited to 'src') diff --git a/src/allocator.rs b/src/allocator.rs deleted file mode 100644 index eaaba5f..0000000 --- a/src/allocator.rs +++ /dev/null @@ -1,204 +0,0 @@ -use core::{ - alloc::{GlobalAlloc, Layout}, - sync::atomic::{AtomicUsize, Ordering::Relaxed}, -}; - -pub struct TalcAllocator( - talc::cell::TalcSyncCell, -); - -impl TalcAllocator { - pub const fn new() -> Self { - Self(talc::cell::TalcSyncCell::new_wasm( - talc::wasm::WasmGrowAndExtend::new(), - )) - } -} - -impl Default for TalcAllocator { - fn default() -> Self { - Self::new() - } -} - -unsafe impl GlobalAlloc for TalcAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - unsafe { self.0.alloc(layout) } - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - unsafe { - self.0.dealloc(ptr, layout); - } - } - - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - unsafe { self.0.alloc_zeroed(layout) } - } - - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - unsafe { self.0.realloc(ptr, layout, new_size) } - } -} - -const CHUNK_SIZE: usize = 64; -const PAGE_SIZE: usize = 64 * 1024; - -unsafe extern "C" { - safe static __heap_base: usize; -} - -pub struct BumpAllocator { - offset: AtomicUsize, - capacity: AtomicUsize, - free_8: AtomicUsize, - free_16: AtomicUsize, - free_32: AtomicUsize, - free_64: AtomicUsize, - free_128: AtomicUsize, - free_256: AtomicUsize, - free_512: AtomicUsize, - free_1024: AtomicUsize, - free_2048: AtomicUsize, - free_4096: AtomicUsize, - free_8192: AtomicUsize, - free_16384: AtomicUsize, - free_32768: AtomicUsize, -} - -fn space_for(layout: Layout) -> usize { - usize::div_ceil(layout.size(), CHUNK_SIZE) * CHUNK_SIZE -} - -fn pop_free_list(list: &AtomicUsize) -> Option<*mut u8> { - let offset = list.swap(0, Relaxed); - if offset != 0 { - // safety: offset is a valid pointer for these operations when non-zero - unsafe { - let ptr = offset as *mut u8; - let next = *ptr.cast::(); - list.swap(next, Relaxed); - Some(ptr) - } - } else { - None - } -} - -unsafe fn push_free_list(list: &AtomicUsize, ptr: *mut u8) { - // safety: all of the pointers here are valid - unsafe { - let new_offset = ptr.addr(); - let current_head = list.swap(new_offset, Relaxed); - *ptr.cast::() = current_head; - } -} - -impl BumpAllocator { - pub const fn new() -> Self { - Self { - offset: AtomicUsize::new(8), - capacity: AtomicUsize::new(PAGE_SIZE - 8), - free_8: AtomicUsize::new(0), - free_16: AtomicUsize::new(0), - free_32: AtomicUsize::new(0), - free_64: AtomicUsize::new(0), - free_128: AtomicUsize::new(0), - free_256: AtomicUsize::new(0), - free_512: AtomicUsize::new(0), - free_1024: AtomicUsize::new(0), - free_2048: AtomicUsize::new(0), - free_4096: AtomicUsize::new(0), - free_8192: AtomicUsize::new(0), - free_16384: AtomicUsize::new(0), - free_32768: AtomicUsize::new(0), - } - } -} - -impl Default for BumpAllocator { - fn default() -> Self { - Self::new() - } -} - -unsafe impl GlobalAlloc for BumpAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - self.offset.fetch_max(__heap_base, Relaxed); - let space_needed = space_for(layout); - let ptr = match space_needed { - 8 => pop_free_list(&self.free_8), - 16 => pop_free_list(&self.free_16), - 32 => pop_free_list(&self.free_32), - 64 => pop_free_list(&self.free_64), - 128 => pop_free_list(&self.free_128), - 256 => pop_free_list(&self.free_256), - 512 => pop_free_list(&self.free_512), - 1024 => pop_free_list(&self.free_1024), - 2048 => pop_free_list(&self.free_2048), - 4096 => pop_free_list(&self.free_4096), - 8192 => pop_free_list(&self.free_8192), - 16384 => pop_free_list(&self.free_16384), - 32768 => pop_free_list(&self.free_32768), - _ => None, - }; - if let Some(ptr) = ptr { - return ptr; - } - - let offset = self.offset.fetch_add(space_needed, Relaxed); - let pointer = offset as *mut u8; - let available_space = self.capacity.load(Relaxed) - offset; - if available_space < layout.size() { - let pages = layout.size().div_ceil(PAGE_SIZE); - core::arch::wasm32::memory_grow(0, pages); - self.capacity.fetch_add(pages * PAGE_SIZE, Relaxed); - } - - pointer - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - let space_used = space_for(layout); - let ptr_offset = ptr.addr(); - if self - .offset - .compare_exchange(ptr_offset + space_used, ptr_offset, Relaxed, Relaxed) - .is_ok() - { - return; - } - - // safety: ptr must be valid and on the heap - unsafe { - match space_used { - 8 => push_free_list(&self.free_8, ptr), - 16 => push_free_list(&self.free_16, ptr), - 32 => push_free_list(&self.free_32, ptr), - 64 => push_free_list(&self.free_64, ptr), - 128 => push_free_list(&self.free_128, ptr), - 256 => push_free_list(&self.free_256, ptr), - 512 => push_free_list(&self.free_512, ptr), - 1024 => push_free_list(&self.free_1024, ptr), - 2048 => push_free_list(&self.free_2048, ptr), - 4096 => push_free_list(&self.free_4096, ptr), - 8192 => push_free_list(&self.free_8192, ptr), - 16384 => push_free_list(&self.free_16384, ptr), - 32768 => push_free_list(&self.free_32768, ptr), - _ => {} - }; - } - } - - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - let space_used = space_for(layout); - if new_size <= space_used { - return ptr; - } - - unsafe { - self.dealloc(ptr, layout); - self.alloc(Layout::from_size_align(new_size, layout.align()).unwrap_unchecked()) - } - } -} diff --git a/src/buffer.rs b/src/buffer.rs deleted file mode 100644 index 78b6bd5..0000000 --- a/src/buffer.rs +++ /dev/null @@ -1,235 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::ScriptContext; - -mod tortuise { - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub safe fn add_cell( - context: u64, - character: u32, - location: u32, - z: u32, - foreground_color: u32, - background_color: u32, - underline_color: u32, - attributes: u32, - ); - pub safe fn window_size(context: u64) -> u32; - } -} - -#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct Cell { - pub character: char, - pub foreground_color: Color, - pub background_color: Color, - pub underline_color: Color, - pub attributes: Attributes, - pub x: u16, - pub y: u16, - pub z: u8, -} - -#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct WindowSize { - pub rows: u16, - pub columns: u16, -} - -#[derive( - Copy, Clone, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize, -)] -pub enum Color { - /// Resets the terminal color. - #[default] - Reset, - - /// Black color. - Black, - - /// Dark grey color. - DarkGrey, - - /// Light red color. - Red, - - /// Dark red color. - DarkRed, - - /// Light green color. - Green, - - /// Dark green color. - DarkGreen, - - /// Light yellow color. - Yellow, - - /// Dark yellow color. - DarkYellow, - - /// Light blue color. - Blue, - - /// Dark blue color. - DarkBlue, - - /// Light magenta color. - Magenta, - - /// Dark magenta color. - DarkMagenta, - - /// Light cyan color. - Cyan, - - /// Dark cyan color. - DarkCyan, - - /// White color. - White, - - /// Grey color. - Grey, - - /// An RGB color. See [RGB color model](https://en.wikipedia.org/wiki/RGB_color_model) for more info. - /// - /// Most UNIX terminals and Windows 10 supported only. - /// See [Platform-specific notes](enum.Color.html#platform-specific-notes) for more info. - Rgb { r: u8, g: u8, b: u8 }, - - /// An ANSI color. See [256 colors - cheat sheet](https://jonasjacek.github.io/colors/) for more info. - /// - /// Most UNIX terminals and Windows 10 supported only. - /// See [Platform-specific notes](enum.Color.html#platform-specific-notes) for more info. - AnsiValue(u8), -} - -#[derive( - Copy, Clone, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize, -)] -pub struct Attributes(u32); - -pub enum Attribute { - /// Increases the text intensity. - Bold = 1, - /// Decreases the text intensity. - Dim = 2, - /// Emphasises the text. - Italic = 4, - /// Underlines the text. - Underlined = 8, - - // Other types of underlining - /// Double underlines the text. - DoubleUnderlined = 16, - /// Undercurls the text. - Undercurled = 32, - /// Underdots the text. - Underdotted = 64, - /// Underdashes the text. - Underdashed = 128, - - /// Makes the text blinking (< 150 per minute). - SlowBlink = 256, - /// Makes the text blinking (>= 150 per minute). - RapidBlink = 512, - /// Swaps foreground and background colors. - Reverse = 1024, - /// Hides the text (also known as Conceal). - Hidden = 2048, - /// Crosses the text. - CrossedOut = 4096, - /// Sets the [Fraktur](https://en.wikipedia.org/wiki/Fraktur) typeface. - /// - /// Mostly used for [mathematical alphanumeric symbols](https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols). - Fraktur = 8192, - /// Makes the text framed. - Framed = 16384, - /// Makes the text encircled. - Encircled = 32768, - /// Draws a line at the top of the text. - OverLined = 65536, -} - -fn color_to_u32(color: Color) -> u32 { - match color { - Color::Reset => 1 << 24, - Color::Black => 1 << 24 | 1, - Color::DarkGrey => 1 << 24 | 2, - Color::Red => 1 << 24 | 3, - Color::DarkRed => 1 << 24 | 4, - Color::Green => 1 << 24 | 5, - Color::DarkGreen => 1 << 24 | 6, - Color::Yellow => 1 << 24 | 7, - Color::DarkYellow => 1 << 24 | 8, - Color::Blue => 1 << 24 | 9, - Color::DarkBlue => 1 << 24 | 10, - Color::Magenta => 1 << 24 | 11, - Color::DarkMagenta => 1 << 24 | 12, - Color::Cyan => 1 << 24 | 13, - Color::DarkCyan => 1 << 24 | 14, - Color::White => 1 << 24 | 15, - Color::Grey => 1 << 24 | 16, - Color::AnsiValue(num) => 2 << 24 | num as u32, - Color::Rgb { r, g, b } => 3 << 24 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32), - } -} - -impl Attributes { - pub fn none() -> Self { - Self(0) - } - - pub fn with(self, attribute: Attribute) -> Self { - Self(self.0 | attribute as u32) - } - - pub fn without(self, attribute: Attribute) -> Self { - Self(self.0 & !(attribute as u32)) - } - - pub fn set(&mut self, attribute: Attribute) { - self.0 |= attribute as u32; - } - - pub fn unset(&mut self, attribute: Attribute) { - self.0 &= !(attribute as u32) - } - - pub fn has(self, attribute: Attribute) -> bool { - self.0 & (attribute as u32) != 0 - } - - pub fn extend(&mut self, attributes: Attributes) { - self.0 |= attributes.0 - } - - pub fn is_empty(self) -> bool { - self.0 == 0 - } -} - -impl ScriptContext { - pub fn add_cell(&self, cell: Cell) { - tortuise::add_cell( - self.0, - cell.character as u32, - (cell.x as u32) << 16 | cell.y as u32, - cell.z as u32, - color_to_u32(cell.foreground_color), - color_to_u32(cell.background_color), - color_to_u32(cell.underline_color), - cell.attributes.0, - ); - } - - pub fn window_size(&self) -> WindowSize { - let size = tortuise::window_size(self.0); - WindowSize { - rows: (size >> 16) as u16, - columns: (size & 0xffff) as u16, - } - } -} diff --git a/src/entity.rs b/src/entity.rs deleted file mode 100644 index 9cf6f17..0000000 --- a/src/entity.rs +++ /dev/null @@ -1,133 +0,0 @@ -use core::{ - alloc::Layout, - marker::PhantomData, - ops::{Deref, DerefMut}, -}; - -use alloc::{ - alloc::{alloc, dealloc}, - borrow::Cow, - string::String, -}; -use serde::{Deserialize, Serialize}; - -use crate::ScriptContext; - -mod tortuise { - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub unsafe fn entity_size(context: u64, name: *const u8, name_len: usize) -> usize; - pub unsafe fn load_entity(context: u64, name: *const u8, name_len: usize, offset: *mut u8); - pub unsafe fn save_entity( - context: u64, - name: *const u8, - name_len: usize, - offset: *const u8, - size: usize, - ); - } -} - -fn load_entity<'de, T: Deserialize<'de>>(context: u64, name: &str) -> Option { - unsafe { - let size = tortuise::entity_size(context, name.as_ptr(), name.len()); - let Ok(layout) = Layout::array::(size) else { - log::error!("Failed to create layout for size: {size}"); - panic!(); - }; - let ptr = alloc(layout); - tortuise::load_entity(context, name.as_ptr(), name.len(), ptr); - let data = core::slice::from_raw_parts(ptr, size); - let data = messagepack_serde::from_slice(data).ok()?; - dealloc(ptr, layout); - Some(data) - } -} - -fn save_entity(context: u64, name: &str, state: &T) { - unsafe { - let data = messagepack_serde::to_vec(state).unwrap(); - tortuise::save_entity( - context, - name.as_ptr(), - name.len(), - data.as_ptr(), - data.len(), - ); - } -} - -pub struct Entity { - name: Cow<'static, str>, - default: fn() -> T, -} - -pub struct EntityRef<'entity, T> { - entity: PhantomData<&'entity Entity>, - data: T, -} - -pub struct EntityMut<'entity, T: Serialize> { - context: u64, - entity: &'entity Entity, - data: T, -} - -impl<'de, T: Serialize + Deserialize<'de>> Entity { - pub const fn new(name: &'static str, default: fn() -> T) -> Self { - Self { - name: Cow::Borrowed(name), - default, - } - } - - pub const fn from_string(name: String, default: fn() -> T) -> Self { - Self { - name: Cow::Owned(name), - default, - } - } - - pub fn get(&self, context: &ScriptContext) -> EntityRef<'_, T> { - EntityRef { - entity: PhantomData, - data: load_entity(context.0, &self.name).unwrap_or_else(self.default), - } - } - - pub fn get_mut(&mut self, context: &ScriptContext) -> EntityMut<'_, T> { - EntityMut { - context: context.0, - entity: self, - data: load_entity(context.0, &self.name).unwrap_or_else(self.default), - } - } -} - -impl Deref for EntityRef<'_, T> { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.data - } -} - -impl Deref for EntityMut<'_, T> { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.data - } -} - -impl DerefMut for EntityMut<'_, T> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.data - } -} - -impl Drop for EntityMut<'_, T> { - fn drop(&mut self) { - save_entity(self.context, &self.entity.name, &self.data); - } -} diff --git a/src/input.rs b/src/input.rs deleted file mode 100644 index a72597d..0000000 --- a/src/input.rs +++ /dev/null @@ -1,84 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::ScriptContext; - -mod tortuise { - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub safe fn is_key_pressed_this_frame(context: u64, keycode: u32) -> u32; - } -} - -/// Represents a key. -#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash, Serialize, Deserialize)] -pub enum KeyCode { - /// Backspace key (Delete on macOS, Backspace on other platforms). - Backspace, - /// Enter key. - Enter, - /// Left arrow key. - Left, - /// Right arrow key. - Right, - /// Up arrow key. - Up, - /// Down arrow key. - Down, - /// Home key. - Home, - /// End key. - End, - /// Page up key. - PageUp, - /// Page down key. - PageDown, - /// Tab key. - Tab, - /// Shift + Tab key. - BackTab, - /// Delete key. (Fn+Delete on macOS, Delete on other platforms) - Delete, - /// Insert key. - Insert, - /// F key. - /// - /// `KeyCode::F(1)` represents F1 key, etc. - F(u8), - /// A character. - /// - /// `KeyCode::Char('c')` represents `c` character, etc. - Char(char), - /// Null. - Null, - /// Escape key. - Esc, -} - -fn key_code_to_number(key_code: KeyCode) -> u32 { - match key_code { - KeyCode::Null => 0, - KeyCode::Backspace => 1 << 24, - KeyCode::Enter => 2 << 24, - KeyCode::Left => 3 << 24, - KeyCode::Right => 4 << 24, - KeyCode::Up => 5 << 24, - KeyCode::Down => 6 << 24, - KeyCode::Home => 7 << 24, - KeyCode::End => 8 << 24, - KeyCode::PageUp => 9 << 24, - KeyCode::PageDown => 10 << 24, - KeyCode::Tab => 11 << 24, - KeyCode::BackTab => 12 << 24, - KeyCode::Delete => 13 << 24, - KeyCode::Insert => 14 << 24, - KeyCode::F(f) => 15 << 24 | f as u32, - KeyCode::Char(c) => 16 << 24 | c as u32, - KeyCode::Esc => 17 << 24, - } -} - -impl ScriptContext { - pub fn is_key_pressed_this_frame(&self, key_code: KeyCode) -> bool { - tortuise::is_key_pressed_this_frame(self.0, key_code_to_number(key_code)) > 0 - } -} diff --git a/src/lib.rs b/src/lib.rs index bc94658..c78eccb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,29 +1,4 @@ -#![no_std] - -extern crate alloc; - -pub mod allocator; -pub mod buffer; -pub mod entity; -pub mod input; -pub mod log; -pub mod process; -pub mod random; -pub mod scene; -pub mod script; -pub mod state; -pub mod storage; -pub mod time; - -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct ScriptContext(u64); - -#[macro_export] -macro_rules! prelude { - () => { - #[global_allocator] - static ALLOCATOR: $crate::allocator::BumpAllocator = - $crate::allocator::BumpAllocator::new(); - }; +cfg_select! { + target_arch = "wasm32" => { pub use tortuise_script_wasm::*; } + _ => { pub use tortuise_script_compiled::*; } } diff --git a/src/log.rs b/src/log.rs deleted file mode 100644 index 306a0d5..0000000 --- a/src/log.rs +++ /dev/null @@ -1,36 +0,0 @@ -use alloc::string::ToString; -use log::{LevelFilter, Log, Metadata, Record, SetLoggerError, set_logger, set_max_level}; - -mod tortuise { - use log::Level; - - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub unsafe fn log(severity: Level, message: *const u8, length: usize); - } -} - -static LOG: TortuiseLogger = TortuiseLogger; - -pub struct TortuiseLogger; - -impl TortuiseLogger { - pub fn init() -> Result<(), SetLoggerError> { - set_logger(&LOG).map(|()| set_max_level(LevelFilter::Trace)) - } -} - -impl Log for TortuiseLogger { - fn enabled(&self, _: &Metadata) -> bool { - true - } - - fn log(&self, record: &Record) { - let message = record.args().to_string(); - unsafe { - tortuise::log(record.level(), message.as_ptr(), message.len()); - } - } - - fn flush(&self) {} -} diff --git a/src/process.rs b/src/process.rs deleted file mode 100644 index ed8c542..0000000 --- a/src/process.rs +++ /dev/null @@ -1,14 +0,0 @@ -use crate::ScriptContext; - -mod tortuise { - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub safe fn exit(context: u64) -> !; - } -} - -impl ScriptContext { - pub fn exit(&self) -> ! { - tortuise::exit(self.0) - } -} diff --git a/src/random.rs b/src/random.rs deleted file mode 100644 index 334b6bf..0000000 --- a/src/random.rs +++ /dev/null @@ -1,73 +0,0 @@ -use rand::{Rng, SeedableRng, TryRng, rngs::SmallRng}; - -mod tortuise { - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub safe fn random_u64() -> u64; - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TortuiseRng(SmallRng); - -impl TortuiseRng { - pub fn new() -> Self { - Self::seed_from_u64(tortuise::random_u64()) - } -} - -impl Default for TortuiseRng { - fn default() -> Self { - Self::new() - } -} - -impl SeedableRng for TortuiseRng { - type Seed = ::Seed; - - fn from_seed(seed: Self::Seed) -> Self { - Self(SmallRng::from_seed(seed)) - } - - fn seed_from_u64(state: u64) -> Self { - Self(SmallRng::seed_from_u64(state)) - } - - fn from_rng(rng: &mut R) -> Self { - Self(SmallRng::from_rng(rng)) - } - - fn try_from_rng(rng: &mut R) -> Result { - Ok(Self(SmallRng::try_from_rng(rng)?)) - } - - fn fork(&mut self) -> Self - where - Self: Rng, - { - Self(self.0.fork()) - } - - fn try_fork(&mut self) -> Result::Error> - where - Self: TryRng, - { - Ok(Self(self.0.try_fork()?)) - } -} - -impl TryRng for TortuiseRng { - type Error = ::Error; - - fn try_next_u32(&mut self) -> Result { - self.0.try_next_u32() - } - - fn try_next_u64(&mut self) -> Result { - self.0.try_next_u64() - } - - fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> { - self.0.try_fill_bytes(dst) - } -} diff --git a/src/scene.rs b/src/scene.rs deleted file mode 100644 index 95284e9..0000000 --- a/src/scene.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::ScriptContext; - -mod tortuise { - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub unsafe fn scene_id_by_name(context: u64, name: *const u8, length: usize) -> usize; - pub safe fn preload_scene(context: u64, id: usize); - pub safe fn is_scene_loaded(context: u64, id: usize) -> u32; - pub safe fn switch_scene(context: u64, id: usize); - } -} - -impl ScriptContext { - pub fn scene_id(&self, name: &str) -> usize { - unsafe { tortuise::scene_id_by_name(self.0, name.as_ptr(), name.len()) } - } - - pub fn preload_scene(&self, name: &str) { - let id = self.scene_id(name); - tortuise::preload_scene(self.0, id); - } - - pub fn is_scene_loaded(&self, name: &str) -> bool { - let id = self.scene_id(name); - tortuise::is_scene_loaded(self.0, id) > 0 - } - - pub fn switch_scene(&self, name: &str) { - let id = self.scene_id(name); - tortuise::switch_scene(self.0, id); - } -} diff --git a/src/script.rs b/src/script.rs deleted file mode 100644 index 0de2b54..0000000 --- a/src/script.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::ScriptContext; - -mod tortuise { - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub unsafe fn script_id_by_name(context: u64, name: *const u8, length: usize) -> usize; - pub safe fn preload_script(context: u64, id: usize); - pub safe fn is_script_loaded(context: u64, id: usize) -> u32; - pub safe fn unload_script(context: u64, id: usize); - pub safe fn activate_script(context: u64, id: usize); - pub safe fn deactivate_script(context: u64, id: usize); - } -} - -impl ScriptContext { - pub fn script_id(&self, name: &str) -> usize { - unsafe { tortuise::script_id_by_name(self.0, name.as_ptr(), name.len()) } - } - - pub fn preload_script(&self, name: &str) { - let id = self.script_id(name); - tortuise::preload_script(self.0, id) - } - - pub fn is_script_loaded(&self, name: &str) -> bool { - let id = self.script_id(name); - tortuise::is_script_loaded(self.0, id) > 0 - } - - pub fn unload_script(&self, name: &str) { - let id = self.script_id(name); - tortuise::unload_script(self.0, id) - } - - pub fn activate_script(&self, name: &str) { - let id = self.script_id(name); - tortuise::activate_script(self.0, id) - } - - pub fn deactivate_script(&self, name: &str) { - let id = self.script_id(name); - tortuise::deactivate_script(self.0, id) - } -} diff --git a/src/state.rs b/src/state.rs deleted file mode 100644 index 8b4de18..0000000 --- a/src/state.rs +++ /dev/null @@ -1,99 +0,0 @@ -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); - } -} diff --git a/src/storage.rs b/src/storage.rs deleted file mode 100644 index 48fdcb4..0000000 --- a/src/storage.rs +++ /dev/null @@ -1,84 +0,0 @@ -use core::{ - alloc::Layout, - ops::{Deref, DerefMut}, -}; - -use alloc::alloc::{alloc, dealloc}; -use serde::{Deserialize, Serialize}; - -use crate::ScriptContext; - -mod tortuise { - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub safe fn storage_size(context: u64) -> usize; - pub unsafe fn load_storage(context: u64, ptr: *mut u8); - pub unsafe fn save_storage(context: u64, ptr: *const u8, size: usize); - } -} - -fn load_storage<'de, T: Deserialize<'de>>(context: u64) -> Option { - unsafe { - let size = tortuise::storage_size(context); - let layout = Layout::array::(size).unwrap(); - let ptr = alloc(layout); - tortuise::load_storage(context, ptr); - let data = core::slice::from_raw_parts(ptr, size); - let data = messagepack_serde::from_slice(data).ok()?; - dealloc(ptr, layout); - Some(data) - } -} - -fn save_storage(context: u64, state: &T) { - unsafe { - let data = messagepack_serde::to_vec(state).unwrap(); - tortuise::save_storage(context, data.as_ptr(), data.len()); - } -} - -pub struct Storage { - initial_state: fn() -> T, -} - -pub struct StorageMut { - context: u64, - data: T, -} - -impl<'de, T: Serialize + Deserialize<'de>> Storage { - pub const fn new(initial_state: fn() -> T) -> Self { - Self { initial_state } - } - - pub fn load(&self, context: &ScriptContext) -> T { - load_storage(context.0).unwrap_or_else(self.initial_state) - } - - pub fn load_mut(&self, context: &ScriptContext) -> StorageMut { - StorageMut { - context: context.0, - data: load_storage(context.0).unwrap_or_else(self.initial_state), - } - } -} - -impl Deref for StorageMut { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.data - } -} - -impl DerefMut for StorageMut { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.data - } -} - -impl Drop for StorageMut { - fn drop(&mut self) { - save_storage(self.context, &self.data); - } -} diff --git a/src/time.rs b/src/time.rs deleted file mode 100644 index 35e1a86..0000000 --- a/src/time.rs +++ /dev/null @@ -1,142 +0,0 @@ -use core::{ - ops::{Add, AddAssign, Sub, SubAssign}, - time::Duration, -}; - -use serde::{Deserialize, Serialize}; - -use crate::ScriptContext; - -mod tortuise { - - #[link(wasm_import_module = "tortuise")] - unsafe extern "C" { - pub safe fn system_now(context: u64) -> u64; - pub safe fn monotonic_now(context: u64) -> u64; - pub safe fn delta_time(context: u64) -> u64; - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -#[repr(transparent)] -#[serde(transparent)] -pub struct SystemTime(u128); - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -#[repr(transparent)] -#[serde(transparent)] -pub struct Instant(u128); - -impl ScriptContext { - pub fn delta_time(&self) -> Duration { - Duration::from_nanos(tortuise::delta_time(self.0)) - } -} - -impl SystemTime { - pub const UNIX_EPOCH: Self = Self(0); - - pub fn now(context: &ScriptContext) -> Self { - Self(tortuise::system_now(context.0) as u128) - } - - pub fn duration_since(self, earlier: SystemTime) -> Option { - if self < earlier { - return None; - } - - Some(Duration::from_nanos_u128(self.0 - earlier.0)) - } - - pub fn checked_add(self, duration: Duration) -> Option { - Some(Self(self.0.checked_add(duration.as_nanos())?)) - } - - pub fn checked_sub(self, duration: Duration) -> Option { - Some(Self(self.0.checked_sub(duration.as_nanos())?)) - } -} - -impl Add for SystemTime { - type Output = Self; - - fn add(self, rhs: Duration) -> Self::Output { - self.checked_add(rhs).unwrap() - } -} - -impl AddAssign for SystemTime { - fn add_assign(&mut self, rhs: Duration) { - *self = self.add(rhs); - } -} - -impl Sub for SystemTime { - type Output = Self; - - fn sub(self, rhs: Duration) -> Self::Output { - self.checked_sub(rhs).unwrap() - } -} - -impl SubAssign for SystemTime { - fn sub_assign(&mut self, rhs: Duration) { - *self = self.sub(rhs) - } -} - -impl Instant { - pub fn now(context: &ScriptContext) -> Self { - Self(tortuise::monotonic_now(context.0) as u128) - } - - pub fn duration_since(self, earlier: Instant) -> Option { - if earlier > self { - return None; - } - - Some(Duration::from_nanos_u128(self.0 - earlier.0)) - } - - pub fn elapsed(self, context: &ScriptContext) -> Duration { - Self::now(context) - .duration_since(self) - .unwrap_or(Duration::ZERO) - } - - pub fn checked_add(self, duration: Duration) -> Option { - Some(Self(self.0.checked_add(duration.as_nanos())?)) - } - - pub fn checked_sub(self, duration: Duration) -> Option { - Some(Self(self.0.checked_sub(duration.as_nanos())?)) - } -} - -impl Add for Instant { - type Output = Self; - - fn add(self, rhs: Duration) -> Self::Output { - self.checked_add(rhs).unwrap() - } -} - -impl AddAssign for Instant { - fn add_assign(&mut self, rhs: Duration) { - *self = self.add(rhs); - } -} - -impl Sub for Instant { - type Output = Self; - - fn sub(self, rhs: Duration) -> Self::Output { - self.checked_sub(rhs).unwrap() - } -} - -impl SubAssign for Instant { - fn sub_assign(&mut self, rhs: Duration) { - *self = self.sub(rhs) - } -} -- cgit v1.3.1