summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2024-08-15 20:23:26 -0400
committerMica White <botahamec@outlook.com>2024-08-25 19:24:37 -0400
commit509e5ce1e17417a70b9bcce8bc6e33c05106811d (patch)
tree5b1fe60a65b5f42a90023ead03c32336033afa1f
parentdb9aa9f1bf49e8bede384b9ceb1e1fb82b522799 (diff)
Start profiling
-rw-r--r--.cargo/Config.toml32
-rw-r--r--.gitignore6
-rw-r--r--.vscode/settings.json124
-rw-r--r--Cargo.toml5
-rw-r--r--alligator_backend.libbin0 -> 625152 bytes
-rw-r--r--book/src/performance.md20
-rw-r--r--console/src/lib.rs43
-rw-r--r--deny.toml12
-rw-r--r--game.json40
-rw-r--r--profiler/Cargo.toml10
-rw-r--r--profiler/src/lib.rs103
-rw-r--r--rustfmt.toml4
-rw-r--r--scripts/Cargo.toml2
-rw-r--r--scripts/bin/benchmark.rs32
-rw-r--r--scripts/bin/ex.wat58
-rw-r--r--scripts/src/libs/allocate.rs152
-rw-r--r--scripts/src/libs/buffer.rs364
-rw-r--r--scripts/src/libs/ctype.rs170
-rw-r--r--scripts/src/libs/math.rs796
-rw-r--r--scripts/src/libs/mod.rs38
-rw-r--r--scripts/src/libs/system.rs308
-rw-r--r--scripts/src/vtable.rs20
-rw-r--r--scripts/src/wasm.rs340
-rw-r--r--shell-spec.txt29
-rw-r--r--src/main.rs299
-rw-r--r--sys/alligator_backend.libbin0 -> 625152 bytes
-rw-r--r--sys/build.rs16
-rw-r--r--sys/src/renderer.rs98
-rw-r--r--sys/src/window.rs232
-rw-r--r--todos.txt4
30 files changed, 1761 insertions, 1596 deletions
diff --git a/.cargo/Config.toml b/.cargo/Config.toml
index 32e1bdc..df202b6 100644
--- a/.cargo/Config.toml
+++ b/.cargo/Config.toml
@@ -1,16 +1,16 @@
-[profile.small]
-opt-level = "z"
-inherits = "release"
-
-[profile.bm]
-lto = true
-inherits = "dev"
-
-[profile.release]
-lto = true
-strip = true
-codegen-units = 1
-panic = "abort"
-
-[profile.dev]
-opt-level = 1
+[profile.small]
+opt-level = "z"
+inherits = "release"
+
+[profile.bm]
+lto = true
+inherits = "dev"
+
+[profile.release]
+lto = true
+strip = true
+codegen-units = 1
+panic = "abort"
+
+[profile.dev]
+opt-level = 1
diff --git a/.gitignore b/.gitignore
index bbbe8bb..0c4f2d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-/target
-/Cargo.lock
-*/target
+/target
+/Cargo.lock
+*/target
*/Cargo.lock \ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index c2985e2..6da577e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,63 +1,63 @@
-{
- "files.associations": {
- "algorithm": "cpp",
- "atomic": "cpp",
- "bit": "cpp",
- "cctype": "cpp",
- "charconv": "cpp",
- "chrono": "cpp",
- "clocale": "cpp",
- "cmath": "cpp",
- "compare": "cpp",
- "concepts": "cpp",
- "cstddef": "cpp",
- "cstdint": "cpp",
- "cstdio": "cpp",
- "cstdlib": "cpp",
- "cstring": "cpp",
- "ctime": "cpp",
- "cwchar": "cpp",
- "exception": "cpp",
- "format": "cpp",
- "forward_list": "cpp",
- "initializer_list": "cpp",
- "iomanip": "cpp",
- "ios": "cpp",
- "iosfwd": "cpp",
- "istream": "cpp",
- "iterator": "cpp",
- "limits": "cpp",
- "locale": "cpp",
- "map": "cpp",
- "memory": "cpp",
- "new": "cpp",
- "optional": "cpp",
- "ostream": "cpp",
- "ratio": "cpp",
- "sstream": "cpp",
- "stdexcept": "cpp",
- "streambuf": "cpp",
- "string": "cpp",
- "system_error": "cpp",
- "tuple": "cpp",
- "type_traits": "cpp",
- "typeinfo": "cpp",
- "utility": "cpp",
- "vector": "cpp",
- "xfacet": "cpp",
- "xiosbase": "cpp",
- "xlocale": "cpp",
- "xlocbuf": "cpp",
- "xlocinfo": "cpp",
- "xlocmes": "cpp",
- "xlocmon": "cpp",
- "xlocnum": "cpp",
- "xloctime": "cpp",
- "xmemory": "cpp",
- "xstddef": "cpp",
- "xstring": "cpp",
- "xtr1common": "cpp",
- "xtree": "cpp",
- "xutility": "cpp"
- }
+{
+ "files.associations": {
+ "algorithm": "cpp",
+ "atomic": "cpp",
+ "bit": "cpp",
+ "cctype": "cpp",
+ "charconv": "cpp",
+ "chrono": "cpp",
+ "clocale": "cpp",
+ "cmath": "cpp",
+ "compare": "cpp",
+ "concepts": "cpp",
+ "cstddef": "cpp",
+ "cstdint": "cpp",
+ "cstdio": "cpp",
+ "cstdlib": "cpp",
+ "cstring": "cpp",
+ "ctime": "cpp",
+ "cwchar": "cpp",
+ "exception": "cpp",
+ "format": "cpp",
+ "forward_list": "cpp",
+ "initializer_list": "cpp",
+ "iomanip": "cpp",
+ "ios": "cpp",
+ "iosfwd": "cpp",
+ "istream": "cpp",
+ "iterator": "cpp",
+ "limits": "cpp",
+ "locale": "cpp",
+ "map": "cpp",
+ "memory": "cpp",
+ "new": "cpp",
+ "optional": "cpp",
+ "ostream": "cpp",
+ "ratio": "cpp",
+ "sstream": "cpp",
+ "stdexcept": "cpp",
+ "streambuf": "cpp",
+ "string": "cpp",
+ "system_error": "cpp",
+ "tuple": "cpp",
+ "type_traits": "cpp",
+ "typeinfo": "cpp",
+ "utility": "cpp",
+ "vector": "cpp",
+ "xfacet": "cpp",
+ "xiosbase": "cpp",
+ "xlocale": "cpp",
+ "xlocbuf": "cpp",
+ "xlocinfo": "cpp",
+ "xlocmes": "cpp",
+ "xlocmon": "cpp",
+ "xlocnum": "cpp",
+ "xloctime": "cpp",
+ "xmemory": "cpp",
+ "xstddef": "cpp",
+ "xstring": "cpp",
+ "xtr1common": "cpp",
+ "xtree": "cpp",
+ "xutility": "cpp"
+ }
} \ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 9a0015a..49cf229 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
[workspace]
-members = ["scripts", "sprites", "sys", "console"]
+members = ["scripts", "sprites", "sys", "console", "profiler"]
resolver = "2"
[package]
@@ -10,6 +10,8 @@ rust-version = "1.65"
publish = false
[dependencies]
+alligator_console = { path = "console" }
+alligator_profiler = { path = "profiler" }
alligator_scripts = { path = "scripts" }
alligator_sprites = { path = "sprites" }
alligator_sys = { path = "sys" }
@@ -17,6 +19,7 @@ alligator_sys = { path = "sys" }
clap = "4"
serde = "1"
serde_json = "1"
+pollster = "0.3"
sha3 = "0.10"
[profile.release]
diff --git a/alligator_backend.lib b/alligator_backend.lib
new file mode 100644
index 0000000..1b79670
--- /dev/null
+++ b/alligator_backend.lib
Binary files differ
diff --git a/book/src/performance.md b/book/src/performance.md
index d769a6f..e97d0ef 100644
--- a/book/src/performance.md
+++ b/book/src/performance.md
@@ -1,10 +1,10 @@
-# Performance
-
-Here are some tips to make your game perform more quickly
-
-## Scripts
-
-Generally, one large WebAssembly script will perform better than many small
-scripts. There is overhead that comes from calling a script, and more scripts
-will result in more overhead. Try to have as few scripts as possible. Ideally,
-you should have no more than 20 scripts enabled at the same time.
+# Performance
+
+Here are some tips to make your game perform more quickly
+
+## Scripts
+
+Generally, one large WebAssembly script will perform better than many small
+scripts. There is overhead that comes from calling a script, and more scripts
+will result in more overhead. Try to have as few scripts as possible. Ideally,
+you should have no more than 20 scripts enabled at the same time.
diff --git a/console/src/lib.rs b/console/src/lib.rs
index afab4af..d98183c 100644
--- a/console/src/lib.rs
+++ b/console/src/lib.rs
@@ -12,6 +12,8 @@ pub struct Console {
sender: Sender<ConsoleMessage>,
}
+pub struct ConsoleLogger(Sender<ConsoleMessage>);
+
pub enum ConsoleMessage {
RuntimeLog {
message: String,
@@ -25,10 +27,18 @@ pub enum ConsoleMessage {
file: String,
line: u32,
},
+ FrameTime {
+ timestamp: i64,
+ },
+ ScopeStart {
+ scope_name: String,
+ timestamp: i64,
+ },
+ ScopeEnd {
+ timestamp: i64,
+ },
}
-pub struct ConsoleLogger(Sender<ConsoleMessage>);
-
impl Console {
pub async fn new(port: u16) -> Result<Self, std::io::Error> {
let tcp_listener = TcpListener::bind((Ipv6Addr::LOCALHOST, port)).await?;
@@ -41,7 +51,7 @@ impl Console {
})
}
- pub fn sender(&self) -> Sender<ConsoleMessage> {
+ fn sender(&self) -> Sender<ConsoleMessage> {
self.sender.clone()
}
@@ -58,6 +68,7 @@ impl Console {
file,
line,
} => {
+ let message = message.replace('\n', "\\n");
let msg = format!("runtimelog {level} {file}:{line} {message}\n");
self.tcp_socket.write(msg.as_bytes()).await?;
}
@@ -67,9 +78,29 @@ impl Console {
file,
line,
} => {
+ let message = message.replace('\n', "\\n");
let msg = format!("scriptlog {level} {file}:{line} {message}\n");
self.tcp_socket.write(msg.as_bytes()).await?;
}
+ ConsoleMessage::FrameTime {
+ timestamp: unix_timestamp,
+ } => {
+ let msg = format!("frametime {unix_timestamp}");
+ self.tcp_socket.write(msg.as_bytes()).await?;
+ }
+ ConsoleMessage::ScopeStart {
+ scope_name,
+ timestamp: unix_timestamp,
+ } => {
+ let msg = format!("scopestart {scope_name} {unix_timestamp}");
+ self.tcp_socket.write(msg.as_bytes()).await?;
+ }
+ ConsoleMessage::ScopeEnd {
+ timestamp: unix_timestamp,
+ } => {
+ let msg = format!("scopeend {unix_timestamp}");
+ self.tcp_socket.write(msg.as_bytes()).await?;
+ }
}
}
@@ -79,6 +110,12 @@ impl Console {
}
}
+impl ConsoleLogger {
+ pub fn send(&self, message: ConsoleMessage) {
+ _ = self.0.send(message).block_on();
+ }
+}
+
impl log::Log for ConsoleLogger {
fn enabled(&self, _: &log::Metadata) -> bool {
true
diff --git a/deny.toml b/deny.toml
index 59a150b..c387c36 100644
--- a/deny.toml
+++ b/deny.toml
@@ -1,7 +1,7 @@
-[licenses]
-allow = ["MIT", "Zlib", "Unlicense"]
-default = "allow"
-copyleft = "deny"
-
-[licenses.private]
+[licenses]
+allow = ["MIT", "Zlib", "Unlicense"]
+default = "allow"
+copyleft = "deny"
+
+[licenses.private]
ignore = true \ No newline at end of file
diff --git a/game.json b/game.json
index 9014385..479c8f1 100644
--- a/game.json
+++ b/game.json
@@ -1,21 +1,21 @@
-{
- "alligator_version": 0,
- "scenes": {
- "black": {
- "initial_sprites": {},
- "initial_scripts": []
- }
- },
- "textures": {},
- "scripts": {},
- "default_scene": "black",
- "default_textures_size_target": 0,
- "sprite_manager_capacity": 0,
- "default_window_width": 640,
- "default_window_height": 480,
- "default_atlas_width": 640,
- "default_atlas_height": 480,
- "default_window_mode": "Windowed",
- "window_title": "Black.exe",
- "vsync": true
+{
+ "alligator_version": 0,
+ "scenes": {
+ "black": {
+ "initial_sprites": {},
+ "initial_scripts": []
+ }
+ },
+ "textures": {},
+ "scripts": {},
+ "default_scene": "black",
+ "default_textures_size_target": 0,
+ "sprite_manager_capacity": 0,
+ "default_window_width": 640,
+ "default_window_height": 480,
+ "default_atlas_width": 640,
+ "default_atlas_height": 480,
+ "default_window_mode": "Windowed",
+ "window_title": "Black.exe",
+ "vsync": true
} \ No newline at end of file
diff --git a/profiler/Cargo.toml b/profiler/Cargo.toml
new file mode 100644
index 0000000..d9c7f2b
--- /dev/null
+++ b/profiler/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "alligator_profiler"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+alligator_console = { path = "../console" }
+
+scopeguard = "1"
+chrono = "0.4" \ No newline at end of file
diff --git a/profiler/src/lib.rs b/profiler/src/lib.rs
new file mode 100644
index 0000000..d23ad24
--- /dev/null
+++ b/profiler/src/lib.rs
@@ -0,0 +1,103 @@
+use std::sync::OnceLock;
+
+use alligator_console::{ConsoleLogger, ConsoleMessage};
+use chrono::{DateTime, Utc};
+use scopeguard::ScopeGuard;
+
+static GLOBAL_PROFILER: OnceLock<Profiler> = OnceLock::new();
+
+struct Profiler {
+ logger: ConsoleLogger,
+ start_time: DateTime<Utc>,
+}
+
+impl Profiler {
+ fn new(logger: ConsoleLogger) -> Self {
+ Self {
+ logger,
+ start_time: Utc::now(),
+ }
+ }
+
+ fn current_timestamp(&self) -> i64 {
+ Utc::now()
+ .signed_duration_since(DateTime::UNIX_EPOCH)
+ .num_microseconds()
+ .unwrap_or(i64::MAX)
+ }
+
+ fn finish_frame(&self) {
+ self.logger.send(ConsoleMessage::FrameTime {
+ timestamp: self.current_timestamp(),
+ })
+ }
+
+ fn start_scope(&self, scope_name: String) {
+ self.logger.send(ConsoleMessage::ScopeStart {
+ scope_name,
+ timestamp: self.current_timestamp(),
+ })
+ }
+
+ fn end_scope(&self) {
+ self.logger.send(ConsoleMessage::ScopeEnd {
+ timestamp: self.current_timestamp(),
+ })
+ }
+}
+
+pub fn set_profiler(logger: ConsoleLogger) {
+ GLOBAL_PROFILER.get_or_init(|| Profiler::new(logger));
+}
+
+pub fn finish_frame() {
+ GLOBAL_PROFILER.get().unwrap().finish_frame();
+}
+
+pub fn start_scope(scope_name: impl AsRef<str>) {
+ GLOBAL_PROFILER
+ .get()
+ .unwrap()
+ .start_scope(scope_name.as_ref().to_string());
+}
+
+pub fn end_scope() {
+ GLOBAL_PROFILER.get().unwrap().end_scope();
+}
+
+pub fn profile_scope(scope_name: impl AsRef<str>) -> ScopeGuard<(), impl FnOnce(())> {
+ start_scope(scope_name);
+ scopeguard::guard((), |_| end_scope())
+}
+
+#[macro_export]
+macro_rules! scope {
+ ($scope_name: expr) => {
+ let _profiling_scope = $crate::profile_scope($scope_name);
+ };
+ () => {
+ let _profiling_scope = $crate::profile_scope("unnamed scope");
+ };
+}
+
+#[macro_export]
+macro_rules! function_name {
+ () => {{
+ fn f() {}
+ fn type_name_of<T>(_: T) -> &'static str {
+ std::any::type_name::<T>()
+ }
+ type_name_of(f)
+ .split("::")
+ .filter(|&part| part != "f")
+ .collect::<Vec<&str>>()
+ .join("::")
+ }};
+}
+
+#[macro_export]
+macro_rules! profile_function {
+ () => {
+ $crate::scope!($crate::function_name!());
+ };
+}
diff --git a/rustfmt.toml b/rustfmt.toml
index 2508efc..bf5ad5c 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1,3 +1,3 @@
-edition = "2021"
-newline_style = "Unix"
+edition = "2021"
+newline_style = "Unix"
hard_tabs = true \ No newline at end of file
diff --git a/scripts/Cargo.toml b/scripts/Cargo.toml
index 88aa2c7..a9fe5e4 100644
--- a/scripts/Cargo.toml
+++ b/scripts/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-wasmtime = "14"
+wasmtime = "15"
rayon = "1"
thiserror = "1"
rand = "0.8"
diff --git a/scripts/bin/benchmark.rs b/scripts/bin/benchmark.rs
index 24f672d..681bace 100644
--- a/scripts/bin/benchmark.rs
+++ b/scripts/bin/benchmark.rs
@@ -1,16 +1,16 @@
-use std::time::Instant;
-
-use scripts::ScriptManager;
-
-fn main() {
- let mut manager = ScriptManager::new();
- let start = Instant::now();
- manager
- .add_wasm_script(Box::from("example"), "bin/ex.wat", false)
- .unwrap();
- println!("Took {} microseconds", start.elapsed().as_micros());
-
- let start = Instant::now();
- manager.run_update_scripts();
- println!("Took {} microseconds", start.elapsed().as_micros());
-}
+use std::time::Instant;
+
+use scripts::ScriptManager;
+
+fn main() {
+ let mut manager = ScriptManager::new();
+ let start = Instant::now();
+ manager
+ .add_wasm_script(Box::from("example"), "bin/ex.wat", false)
+ .unwrap();
+ println!("Took {} microseconds", start.elapsed().as_micros());
+
+ let start = Instant::now();
+ manager.run_update_scripts();
+ println!("Took {} microseconds", start.elapsed().as_micros());
+}
diff --git a/scripts/bin/ex.wat b/scripts/bin/ex.wat
index af461bd..3f8e609 100644
--- a/scripts/bin/ex.wat
+++ b/scripts/bin/ex.wat
@@ -1,29 +1,29 @@
-(module
- (import "alligator" "abs" (func $abs (param i32) (result i32)))
- (func $add1
- (local $i i32)
- (loop $myloop
- local.get $i
- i32.const 1
- i32.add
- local.set $i
-
- local.get $i
- call $abs
-
- local.get $i
- i32.const 40
- i32.lt_s
- br_if $myloop
-
- drop
- )
- )
- (func $add2 nop)
- (export "begin" (func $add2))
- (export "update" (func $add1))
- (memory (;0;) 16)
- (export "memory" (memory 0))
- (global $base i32 (i32.const 1))
- (export "__heap_base" (global $base))
-)
+(module
+ (import "alligator" "abs" (func $abs (param i32) (result i32)))
+ (func $add1
+ (local $i i32)
+ (loop $myloop
+ local.get $i
+ i32.const 1
+ i32.add
+ local.set $i
+
+ local.get $i
+ call $abs
+
+ local.get $i
+ i32.const 40
+ i32.lt_s
+ br_if $myloop
+
+ drop
+ )
+ )
+ (func $add2 nop)
+ (export "begin" (func $add2))
+ (export "update" (func $add1))
+ (memory (;0;) 16)
+ (export "memory" (memory 0))
+ (global $base i32 (i32.const 1))
+ (export "__heap_base" (global $base))
+)
diff --git a/scripts/src/libs/allocate.rs b/scripts/src/libs/allocate.rs
index 7f2825d..c2bb2cf 100644
--- a/scripts/src/libs/allocate.rs
+++ b/scripts/src/libs/allocate.rs
@@ -1,76 +1,76 @@
-use wasmtime::Caller;
-
-use crate::{ScriptManager, WasmScriptState};
-
-use super::{
- system::{_alloc, _get_memory},
- LIBRARY_NAME,
-};
-
-fn allocate_zeroed(mut caller: Caller<'_, WasmScriptState>, size: u32, align: u32) -> u32 {
- let Some((ptr, data)) = _alloc(&mut caller, size, align) else {
- return 0;
- };
-
- data.fill(0);
- ptr
-}
-
-fn reallocate(
- mut caller: Caller<'_, WasmScriptState>,
- ptr: u32,
- size: u32,
- new_size: u32,
- align: u32,
-) -> u32 {
- if new_size < size {
- return ptr;
- }
-
- let bump_pointer = &mut caller.data_mut().bump_pointer;
- if *bump_pointer == ptr + size {
- *bump_pointer = ptr;
- let Some((new_ptr, _)) = _alloc(&mut caller, new_size, align) else {
- return 4;
- };
- return new_ptr;
- }
-
- let (_, original) = _get_memory(&mut caller);
- let Some(original) = original.get(ptr as usize..(ptr + size) as usize) else {
- return 4;
- };
- let original = original.to_vec();
-
- let Some((new_ptr, data)) = _alloc(&mut caller, new_size, align) else {
- return 0;
- };
-
- data.get_mut(..size as usize)
- .unwrap()
- .clone_from_slice(&original);
- new_ptr
-}
-
-fn duplicate(mut caller: Caller<'_, WasmScriptState>, ptr: u32, size: u32, align: u32) -> u32 {
- let (_, original) = _get_memory(&mut caller);
- let Some(original) = original.get(ptr as usize..(ptr + size) as usize) else {
- return 4;
- };
- let original = original.to_vec();
-
- let Some((new_ptr, data)) = _alloc(&mut caller, size, align) else {
- return 0;
- };
-
- data.clone_from_slice(&original);
- new_ptr
-}
-
-pub fn library(manager: &mut ScriptManager) -> Option<()> {
- manager.add_library_function(LIBRARY_NAME, "calloc", allocate_zeroed)?;
- manager.add_library_function(LIBRARY_NAME, "realloc", reallocate)?;
- manager.add_library_function(LIBRARY_NAME, "memdup", duplicate)?;
-
- Some(())
-}
+use wasmtime::Caller;
+
+use crate::{ScriptManager, WasmScriptState};
+
+use super::{
+ system::{_alloc, _get_memory},
+ LIBRARY_NAME,
+};
+
+fn allocate_zeroed(mut caller: Caller<'_, WasmScriptState>, size: u32, align: u32) -> u32 {
+ let Some((ptr, data)) = _alloc(&mut caller, size, align) else {
+ return 0;
+ };
+
+ data.fill(0);
+ ptr
+}
+
+fn reallocate(
+ mut caller: Caller<'_, WasmScriptState>,
+ ptr: u32,
+ size: u32,
+ new_size: u32,
+ align: u32,
+) -> u32 {
+ if new_size < size {
+ return ptr;
+ }
+
+ let bump_pointer = &mut caller.data_mut().bump_pointer;
+ if *bump_pointer == ptr + size {
+ *bump_pointer = ptr;
+ let Some((new_ptr, _)) = _alloc(&mut caller, new_size, align) else {
+ return 4;
+ };
+ return new_ptr;
+ }
+
+ let (_, original) = _get_memory(&mut caller);
+ let Some(original) = original.get(ptr as usize..(ptr + size) as usize) else {
+ return 4;
+ };
+ let original = original.to_vec();
+
+ let Some((new_ptr, data)) = _alloc(&mut caller, new_size, align) else {
+ return 0;
+ };
+
+ data.get_mut(..size as usize)
+ .unwrap()
+ .clone_from_slice(&original);
+ new_ptr
+}
+
+fn duplicate(mut caller: Caller<'_, WasmScriptState>, ptr: u32, size: u32, align: u32) -> u32 {
+ let (_, original) = _get_memory(&mut caller);
+ let Some(original) = original.get(ptr as usize..(ptr + size) as usize) else {
+ return 4;
+ };
+ let original = original.to_vec();
+
+ let Some((new_ptr, data)) = _alloc(&mut caller, size, align) else {
+ return 0;
+ };
+
+ data.clone_from_slice(&original);
+ new_ptr
+}
+
+pub fn library(manager: &mut ScriptManager) -> Option<()> {
+ manager.add_library_function(LIBRARY_NAME, "calloc", allocate_zeroed)?;
+ manager.add_library_function(LIBRARY_NAME, "realloc", reallocate)?;
+ manager.add_library_function(LIBRARY_NAME, "memdup", duplicate)?;
+
+ Some(())
+}
diff --git a/scripts/src/libs/buffer.rs b/scripts/src/libs/buffer.rs
index b4cee77..0958260 100644
--- a/scripts/src/libs/buffer.rs
+++ b/scripts/src/libs/buffer.rs
@@ -1,182 +1,182 @@
-use wasmtime::Caller;
-
-use crate::{ScriptManager, WasmScriptState};
-
-use super::{system::_get_memory, LIBRARY_NAME};
-
-fn memory_search(mut caller: Caller<'_, WasmScriptState>, ptr: u32, ch: u32, len: u32) -> u32 {
- let (_, mem_ptr) = _get_memory(&mut caller);
- let len = len as usize;
- let ptr = ptr as usize;
- let ch = ch as u8;
- if (len + ptr) > mem_ptr.len() {
- return 4;
- }
-
- for i in 0..len {
- if mem_ptr[ptr + i] == ch {
- return (ptr + i) as u32;
- }
- }
-
- 0
-}
-
-fn memory_search_last(mut caller: Caller<'_, WasmScriptState>, ptr: u32, ch: u32, len: u32) -> u32 {
- let (_, mem_ptr) = _get_memory(&mut caller);
- let len = len as usize;
- let ptr = ptr as usize;
- let ch = ch as u8;
- if (len + ptr) > mem_ptr.len() {
- return 4;
- }
-
- for i in 0..len {
- let index = ptr + len - i - 1;
- if mem_ptr[index] == ch {
- return index as u32;
- }
- }
-
- 0
-}
-
-fn memory_compare(
- mut caller: Caller<'_, WasmScriptState>,
- lhs: u32,
- rhs: u32,
- len: u32,
-) -> (u32, u32) {
- let (_, mem_ptr) = _get_memory(&mut caller);
- let len = len as usize;
- let lhs = lhs as usize;
- let rhs = rhs as usize;
- if (len + lhs) > mem_ptr.len() || (len + rhs) > mem_ptr.len() {
- return (4, 0);
- }
-
- for i in 0..len {
- let diff = mem_ptr[lhs + i] - mem_ptr[rhs + i];
- if diff != 0 {
- return (0, diff as u32);
- }
- }
-
- (0, 0)
-}
-
-fn memory_fill(mut caller: Caller<'_, WasmScriptState>, dest: u32, ch: u32, len: u32) -> u32 {
- let (_, mem_ptr) = _get_memory(&mut caller);
- let len = len as usize;
- let dest = dest as usize;
- let ch = ch as u8;
-
- if (len + dest) > mem_ptr.len() {
- return 4;
- }
-
- for i in 0..len {
- mem_ptr[dest + i] = ch;
- }
-
- 0
-}
-
-fn memory_copy(mut caller: Caller<'_, WasmScriptState>, dest: u32, src: u32, len: u32) -> u32 {
- let (_, mem_ptr) = _get_memory(&mut caller);
- let len = len as usize;
- let dest = dest as usize;
- let src = src as usize;
- if (len + dest) > mem_ptr.len() || (len + src) > mem_ptr.len() {
- return 4;
- }
-
- // check for overlap
- if (dest < src && dest + len > src) || (src < dest && src + len > dest) {
- let src = mem_ptr[src..src + len].to_vec();
- let dest = &mut mem_ptr[dest..dest + len];
- dest.clone_from_slice(&src);
- } else {
- for i in 0..len {
- mem_ptr[dest + i] = mem_ptr[src + i];
- }
- }
-
- 0
-}
-
-fn memory_copy_until(
- mut caller: Caller<'_, WasmScriptState>,
- dest: u32,
- src: u32,
- len: u32,
- delimiter: u32,
-) -> u32 {
- let (_, mem_ptr) = _get_memory(&mut caller);
- let len = len as usize;
- let dest = dest as usize;
- let src = src as usize;
- let delimiter = delimiter as u8;
- if (len + dest) > mem_ptr.len() || (len + src) > mem_ptr.len() {
- return 4;
- }
-
- // check for overlap
- if (dest < src && dest + len > src) || (src < dest && src + len > dest) {
- let cloned_src = mem_ptr[src..src + len].to_vec();
- let dest = &mut mem_ptr[dest..dest + len];
- for i in 0..len {
- let ch = cloned_src[i];
- dest[i] = ch;
- if ch == delimiter {
- return (src + i + 1) as u32;
- }
- }
- } else {
- for i in 0..len {
- let ch = mem_ptr[src + i];
- mem_ptr[dest + i] = ch;
- if ch == delimiter {
- return (src + i + 1) as u32;
- }
- }
- }
-
- 0
-}
-
-fn memory_concatenate(
- mut caller: Caller<'_, WasmScriptState>,
- dest: u32,
- src: u32,
- dest_len: u32,
- src_len: u32,
-) -> u32 {
- let (_, mem_ptr) = _get_memory(&mut caller);
- let dest = dest as usize;
- let src = src as usize;
- let dest_len = dest_len as usize;
- let src_len = src_len as usize;
- if (dest_len + src_len + dest) > mem_ptr.len() || (src_len + src) > mem_ptr.len() {
- return 4;
- }
-
- let src = mem_ptr[src..src + src_len].to_vec();
- let dest_offset = dest + dest_len;
- let dest = &mut mem_ptr[dest_offset..dest_offset + src_len];
- dest.clone_from_slice(&src);
-
- 0
-}
-
-pub fn library(manager: &mut ScriptManager) -> Option<()> {
- manager.add_library_function(LIBRARY_NAME, "memchr", memory_search)?;
- manager.add_library_function(LIBRARY_NAME, "memrchr", memory_search_last)?;
- manager.add_library_function(LIBRARY_NAME, "memcmp", memory_compare)?;
- manager.add_library_function(LIBRARY_NAME, "memset", memory_fill)?;
- manager.add_library_function(LIBRARY_NAME, "memcpy", memory_copy)?;
- manager.add_library_function(LIBRARY_NAME, "memccpy", memory_copy_until)?;
- manager.add_library_function(LIBRARY_NAME, "memcat", memory_concatenate)?;
-
- Some(())
-}
+use wasmtime::Caller;
+
+use crate::{ScriptManager, WasmScriptState};
+
+use super::{system::_get_memory, LIBRARY_NAME};
+
+fn memory_search(mut caller: Caller<'_, WasmScriptState>, ptr: u32, ch: u32, len: u32) -> u32 {
+ let (_, mem_ptr) = _get_memory(&mut caller);
+ let len = len as usize;
+ let ptr = ptr as usize;
+ let ch = ch as u8;
+ if (len + ptr) > mem_ptr.len() {
+ return 4;
+ }
+
+ for i in 0..len {
+ if mem_ptr[ptr + i] == ch {
+ return (ptr + i) as u32;
+ }
+ }
+
+ 0
+}
+
+fn memory_search_last(mut caller: Caller<'_, WasmScriptState>, ptr: u32, ch: u32, len: u32) -> u32 {
+ let (_, mem_ptr) = _get_memory(&mut caller);
+ let len = len as usize;
+ let ptr = ptr as usize;
+ let ch = ch as u8;
+ if (len + ptr) > mem_ptr.len() {
+ return 4;
+ }
+
+ for i in 0..len {
+ let index = ptr + len - i - 1;
+ if mem_ptr[index] == ch {
+ return index as u32;
+ }
+ }
+
+ 0
+}
+
+fn memory_compare(
+ mut caller: Caller<'_, WasmScriptState>,
+ lhs: u32,
+ rhs: u32,
+ len: u32,
+) -> (u32, u32) {
+ let (_, mem_ptr) = _get_memory(&mut caller);
+ let len = len as usize;
+ let lhs = lhs as usize;
+ let rhs = rhs as usize;
+ if (len + lhs) > mem_ptr.len() || (len + rhs) > mem_ptr.len() {
+ return (4, 0);
+ }
+
+ for i in 0..len {
+ let diff = mem_ptr[lhs + i] - mem_ptr[rhs + i];
+ if diff != 0 {
+ return (0, diff as u32);
+ }
+ }
+
+ (0, 0)
+}
+
+fn memory_fill(mut caller: Caller<'_, WasmScriptState>, dest: u32, ch: u32, len: u32) -> u32 {
+ let (_, mem_ptr) = _get_memory(&mut caller);
+ let len = len as usize;
+ let dest = dest as usize;
+ let ch = ch as u8;
+
+ if (len + dest) > mem_ptr.len() {
+ return 4;
+ }
+
+ for i in 0..len {
+ mem_ptr[dest + i] = ch;
+ }
+
+ 0
+}
+
+fn memory_copy(mut caller: Caller<'_, WasmScriptState>, dest: u32, src: u32, len: u32) -> u32 {
+ let (_, mem_ptr) = _get_memory(&mut caller);
+ let len = len as usize;
+ let dest = dest as usize;
+ let src = src as usize;
+ if (len + dest) > mem_ptr.len() || (len + src) > mem_ptr.len() {
+ return 4;
+ }
+
+ // check for overlap
+ if (dest < src && dest + len > src) || (src < dest && src + len > dest) {
+ let src = mem_ptr[src..src + len].to_vec();
+ let dest = &mut mem_ptr[dest..dest + len];
+ dest.clone_from_slice(&src);
+ } else {
+ for i in 0..len {
+ mem_ptr[dest + i] = mem_ptr[src + i];
+ }
+ }
+
+ 0
+}
+
+fn memory_copy_until(
+ mut caller: Caller<'_, WasmScriptState>,
+ dest: u32,
+ src: u32,
+ len: u32,
+ delimiter: u32,
+) -> u32 {
+ let (_, mem_ptr) = _get_memory(&mut caller);
+ let len = len as usize;
+ let dest = dest as usize;
+ let src = src as usize;
+ let delimiter = delimiter as u8;
+ if (len + dest) > mem_ptr.len() || (len + src) > mem_ptr.len() {
+ return 4;
+ }
+
+ // check for overlap
+ if (dest < src && dest + len > src) || (src < dest && src + len > dest) {
+ let cloned_src = mem_ptr[src..src + len].to_vec();
+ let dest = &mut mem_ptr[dest..dest + len];
+ for i in 0..len {
+ let ch = cloned_src[i];
+ dest[i] = ch;
+ if ch == delimiter {
+ return (src + i + 1) as u32;
+ }
+ }
+ } else {
+ for i in 0..len {
+ let ch = mem_ptr[src + i];
+ mem_ptr[dest + i] = ch;
+ if ch == delimiter {
+ return (src + i + 1) as u32;
+ }
+ }
+ }
+
+ 0
+}
+
+fn memory_concatenate(
+ mut caller: Caller<'_, WasmScriptState>,
+ dest: u32,
+ src: u32,
+ dest_len: u32,
+ src_len: u32,
+) -> u32 {
+ let (_, mem_ptr) = _get_memory(&mut caller);
+ let dest = dest as usize;
+ let src = src as usize;
+ let dest_len = dest_len as usize;
+ let src_len = src_len as usize;
+ if (dest_len + src_len + dest) > mem_ptr.len() || (src_len + src) > mem_ptr.len() {
+ return 4;
+ }
+
+ let src = mem_ptr[src..src + src_len].to_vec();
+ let dest_offset = dest + dest_len;
+ let dest = &mut mem_ptr[dest_offset..dest_offset + src_len];
+ dest.clone_from_slice(&src);
+
+ 0
+}
+
+pub fn library(manager: &mut ScriptManager) -> Option<()> {
+ manager.add_library_function(LIBRARY_NAME, "memchr", memory_search)?;
+ manager.add_library_function(LIBRARY_NAME, "memrchr", memory_search_last)?;
+ manager.add_library_function(LIBRARY_NAME, "memcmp", memory_compare)?;
+ manager.add_library_function(LIBRARY_NAME, "memset", memory_fill)?;
+ manager.add_library_function(LIBRARY_NAME, "memcpy", memory_copy)?;
+ manager.add_library_function(LIBRARY_NAME, "memccpy", memory_copy_until)?;
+ manager.add_library_function(LIBRARY_NAME, "memcat", memory_concatenate)?;
+
+ Some(())
+}
diff --git a/scripts/src/libs/ctype.rs b/scripts/src/libs/ctype.rs
index ca4f326..1236936 100644
--- a/scripts/src/libs/ctype.rs
+++ b/scripts/src/libs/ctype.rs
@@ -1,85 +1,85 @@
-use crate::{libs::LIBRARY_NAME, ScriptManager};
-
-fn char_is(func: impl Fn(char) -> bool, ch: u32) -> u32 {
- let Some(ch) = char::from_u32(ch) else {
- return 0;
- };
-
- func(ch) as u32
-}
-
-macro_rules! ctype {
- (fn $fn_name: ident => $fn: expr;) => {
- fn $fn_name(ch: u32) -> u32 {
- char_is($fn, ch)
- }
- };
- (fn $fn_name: ident => $fn: expr; $(fn $fn_name2: ident => $fn2: expr;)*) => {
- fn $fn_name(ch: u32) -> u32 {
- char_is($fn, ch)
- }
- ctype!($(fn $fn_name2 => $fn2;)*);
- };
-}
-
-ctype!(
- fn is_alphanumeric => |ch| ch.is_alphanumeric();
- fn is_alphabetic => |ch| ch.is_alphabetic();
- fn is_lowercase => |ch| ch.is_lowercase();
- fn is_uppercase => |ch| ch.is_uppercase();
- fn is_control => |ch| ch.is_control();
- fn is_whitespace => |ch| ch.is_whitespace();
- fn is_ascii_alphanumeric => |ch| ch.is_ascii_alphanumeric();
- fn is_ascii_alphabetic => |ch| ch.is_ascii_alphabetic();
- fn is_ascii_lowercase => |ch| ch.is_ascii_lowercase();
- fn is_ascii_uppercase => |ch| ch.is_ascii_lowercase();
- fn is_ascii_digit => |ch| ch.is_ascii_digit();
- fn is_ascii_hexdigit => |ch| ch.is_ascii_hexdigit();
- fn is_ascii_control => |ch| ch.is_ascii_control();
- fn is_ascii_graphical => |ch| ch.is_ascii_graphic();
- fn is_ascii_whitespace => |ch| ch.is_ascii_whitespace();
- fn is_ascii_blank => |ch| ch == ' ' || ch == '\t';
- fn is_ascii_printable => |ch| ch.is_alphanumeric() || ch.is_ascii_punctuation();
- fn is_ascii_punctuation => |ch| ch.is_ascii_punctuation();
-);
-
-fn to_ascii_lower(ch: u32) -> u32 {
- let Some(ch) = char::from_u32(ch) else {
- return ch;
- };
-
- ch.to_ascii_lowercase() as u32
-}
-
-fn to_ascii_upper(ch: u32) -> u32 {
- let Some(ch) = char::from_u32(ch) else {
- return ch;
- };
-
- ch.to_ascii_uppercase() as u32
-}
-
-pub fn library(manager: &mut ScriptManager) -> Option<()> {
- manager.add_library_function(LIBRARY_NAME, "iswalnum", is_alphanumeric)?;
- manager.add_library_function(LIBRARY_NAME, "iswalpha", is_alphabetic)?;
- manager.add_library_function(LIBRARY_NAME, "iswlower", is_lowercase)?;
- manager.add_library_function(LIBRARY_NAME, "iswupper", is_uppercase)?;
- manager.add_library_function(LIBRARY_NAME, "iswcntrl", is_control)?;
- manager.add_library_function(LIBRARY_NAME, "iswspace", is_whitespace)?;
- manager.add_library_function(LIBRARY_NAME, "isalnum", is_ascii_alphanumeric)?;
- manager.add_library_function(LIBRARY_NAME, "isalpha", is_ascii_alphabetic)?;
- manager.add_library_function(LIBRARY_NAME, "islower", is_ascii_lowercase)?;
- manager.add_library_function(LIBRARY_NAME, "isupper", is_ascii_uppercase)?;
- manager.add_library_function(LIBRARY_NAME, "isdigit", is_ascii_digit)?;
- manager.add_library_function(LIBRARY_NAME, "isxdigit", is_ascii_hexdigit)?;
- manager.add_library_function(LIBRARY_NAME, "iscntrl", is_ascii_control)?;
- manager.add_library_function(LIBRARY_NAME, "isgraph", is_ascii_graphical)?;
- manager.add_library_function(LIBRARY_NAME, "isspace", is_ascii_whitespace)?;
- manager.add_library_function(LIBRARY_NAME, "isblank", is_ascii_blank)?;
- manager.add_library_function(LIBRARY_NAME, "isprint", is_ascii_printable)?;
- manager.add_library_function(LIBRARY_NAME, "ispunct", is_ascii_punctuation)?;
- manager.add_library_function(LIBRARY_NAME, "tolower", to_ascii_lower)?;
- manager.add_library_function(LIBRARY_NAME, "toupper", to_ascii_upper)?;
-
- Some(())
-}
+use crate::{libs::LIBRARY_NAME, ScriptManager};
+
+fn char_is(func: impl Fn(char) -> bool, ch: u32) -> u32 {
+ let Some(ch) = char::from_u32(ch) else {
+ return 0;
+ };
+
+ func(ch) as u32
+}
+
+macro_rules! ctype {
+ (fn $fn_name: ident => $fn: expr;) => {
+ fn $fn_name(ch: u32) -> u32 {
+ char_is($fn, ch)
+ }
+ };
+ (fn $fn_name: ident => $fn: expr; $(fn $fn_name2: ident => $fn2: expr;)*) => {
+ fn $fn_name(ch: u32) -> u32 {
+ char_is($fn, ch)
+ }
+ ctype!($(fn $fn_name2 => $fn2;)*);
+ };
+}
+
+ctype!(
+ fn is_alphanumeric => |ch| ch.is_alphanumeric();
+ fn is_alphabetic => |ch| ch.is_alphabetic();
+ fn is_lowercase => |ch| ch.is_lowercase();
+ fn is_uppercase => |ch| ch.is_uppercase();
+ fn is_control => |ch| ch.is_control();
+ fn is_whitespace => |ch| ch.is_whitespace();
+ fn is_ascii_alphanumeric => |ch| ch.is_ascii_alphanumeric();
+ fn is_ascii_alphabetic => |ch| ch.is_ascii_alphabetic();
+ fn is_ascii_lowercase => |ch| ch.is_ascii_lowercase();
+ fn is_ascii_uppercase => |ch| ch.is_ascii_lowercase();
+ fn is_ascii_digit => |ch| ch.is_ascii_digit();
+ fn is_ascii_hexdigit => |ch| ch.is_ascii_hexdigit();
+ fn is_ascii_control => |ch| ch.is_ascii_control();
+ fn is_ascii_graphical => |ch| ch.is_ascii_graphic();
+ fn is_ascii_whitespace => |ch| ch.is_ascii_whitespace();
+ fn is_ascii_blank => |ch| ch == ' ' || ch == '\t';
+ fn is_ascii_printable => |ch| ch.is_alphanumeric() || ch.is_ascii_punctuation();
+ fn is_ascii_punctuation => |ch| ch.is_ascii_punctuation();
+);
+
+fn to_ascii_lower(ch: u32) -> u32 {
+ let Some(ch) = char::from_u32(ch) else {
+ return ch;
+ };
+
+ ch.to_ascii_lowercase() as u32
+}
+
+fn to_ascii_upper(ch: u32) -> u32 {
+ let Some(ch) = char::from_u32(ch) else {
+ return ch;
+ };
+
+ ch.to_ascii_uppercase() as u32
+}
+
+pub fn library(manager: &mut ScriptManager) -> Option<()> {
+ manager.add_library_function(LIBRARY_NAME, "iswalnum", is_alphanumeric)?;
+ manager.add_library_function(LIBRARY_NAME, "iswalpha", is_alphabetic)?;
+ manager.add_library_function(LIBRARY_NAME, "iswlower", is_lowercase)?;
+ manager.add_library_function(LIBRARY_NAME, "iswupper", is_uppercase)?;
+ manager.add_library_function(LIBRARY_NAME, "iswcntrl", is_control)?;
+ manager.add_library_function(LIBRARY_NAME, "iswspace", is_whitespace)?;
+ manager.add_library_function(LIBRARY_NAME, "isalnum", is_ascii_alphanumeric)?;
+ manager.add_library_function(LIBRARY_NAME, "isalpha", is_ascii_alphabetic)?;
+ manager.add_library_function(LIBRARY_NAME, "islower", is_ascii_lowercase)?;
+ manager.add_library_function(LIBRARY_NAME, "isupper", is_ascii_uppercase)?;
+ manager.add_library_function(LIBRARY_NAME, "isdigit", is_ascii_digit)?;
+ manager.add_library_function(LIBRARY_NAME, "isxdigit", is_ascii_hexdigit)?;
+ manager.add_library_function(LIBRARY_NAME, "iscntrl", is_ascii_control)?;
+ manager.add_library_function(LIBRARY_NAME, "isgraph", is_ascii_graphical)?;
+ manager.add_library_function(LIBRARY_NAME, "isspace", is_ascii_whitespace)?;
+ manager.add_library_function(LIBRARY_NAME, "isblank", is_ascii_blank)?;
+ manager.add_library_function(LIBRARY_NAME, "isprint", is_ascii_printable)?;
+ manager.add_library_function(LIBRARY_NAME, "ispunct", is_ascii_punctuation)?;
+ manager.add_library_function(LIBRARY_NAME, "tolower", to_ascii_lower)?;
+ manager.add_library_function(LIBRARY_NAME, "toupper", to_ascii_upper)?;
+
+ Some(())
+}
diff --git a/scripts/src/libs/math.rs b/scripts/src/libs/math.rs
index 4aae3c3..c20f322 100644
--- a/scripts/src/libs/math.rs
+++ b/scripts/src/libs/math.rs
@@ -1,398 +1,398 @@
-use crate::ScriptManager;
-
-use super::LIBRARY_NAME;
-
-fn abs_i32(n: i32) -> i32 {
- n.abs()
-}
-
-fn abs_i64(n: i64) -> i64 {
- n.abs()
-}
-
-fn mod_f32(x: f32, y: f32) -> f32 {
- libm::fmodf(x, y)
-}
-
-fn mod_f64(x: f64, y: f64) -> f64 {
- libm::fmod(x, y)
-}
-
-fn remainder_f32(x: f32, y: f32) -> f32 {
- libm::remainderf(x, y)
-}
-
-fn remainder_f64(x: f64, y: f64) -> f64 {
- libm::remainder(x, y)
-}
-
-fn mul_add_f32(x: f32, y: f32, z: f32) -> f32 {
- x.mul_add(y, z)
-}
-
-fn mul_add_f64(x: f64, y: f64, z: f64) -> f64 {
- x.mul_add(y, z)
-}
-
-fn fdim_f32(x: f32, y: f32) -> f32 {
- libm::fdimf(x, y)
-}
-
-fn fdim_f64(x: f64, y: f64) -> f64 {
- libm::fdim(x, y)
-}
-
-fn exp_f32(x: f32) -> f32 {
- x.exp()
-}
-
-fn exp_f64(x: f64) -> f64 {
- x.exp()
-}
-
-fn exp2_f32(x: f32) -> f32 {
- x.exp2()
-}
-
-fn exp2_f64(x: f64) -> f64 {
- x.exp2()
-}
-
-fn expm1_f32(x: f32) -> f32 {
- x.exp_m1()
-}
-
-fn expm1_f64(x: f64) -> f64 {
- x.exp_m1()
-}
-
-fn ln_f32(x: f32) -> f32 {
- x.ln()
-}
-
-fn ln_f64(x: f64) -> f64 {
- x.ln()
-}
-
-fn log10_f32(x: f32) -> f32 {
- x.log10()
-}
-
-fn log10_f64(x: f64) -> f64 {
- x.log10()
-}
-
-fn log2_f32(x: f32) -> f32 {
- x.log2()
-}
-
-fn log2_f64(x: f64) -> f64 {
- x.log2()
-}
-
-fn ln1p_f32(x: f32) -> f32 {
- x.ln_1p()
-}
-
-fn ln1p_f64(x: f64) -> f64 {
- x.ln_1p()
-}
-
-fn pow_f32(base: f32, exponent: f32) -> f32 {
- base.powf(exponent)
-}
-
-fn pow_f64(base: f64, exponent: f64) -> f64 {
- base.powf(exponent)
-}
-
-fn cbrt_f32(x: f32) -> f32 {
- x.cbrt()
-}
-
-fn cbrt_f64(x: f64) -> f64 {
- x.cbrt()
-}
-
-fn hypotenuse_f32(x: f32, y: f32) -> f32 {
- x.hypot(y)
-}
-
-fn hypotenuse_f64(x: f64, y: f64) -> f64 {
- x.hypot(y)
-}
-
-fn sin_f32(x: f32) -> f32 {
- x.sin()
-}
-
-fn sin_f64(x: f64) -> f64 {
- x.sin()
-}
-
-fn cos_f32(x: f32) -> f32 {
- x.cos()
-}
-
-fn cos_f64(x: f64) -> f64 {
- x.cos()
-}
-
-fn tan_f32(x: f32) -> f32 {
- x.tan()
-}
-
-fn tan_f64(x: f64) -> f64 {
- x.tan()
-}
-
-fn asin_f32(x: f32) -> f32 {
- x.asin()
-}
-
-fn asin_f64(x: f64) -> f64 {
- x.asin()
-}
-
-fn acos_f32(x: f32) -> f32 {
- x.acos()
-}
-
-fn acos_f64(x: f64) -> f64 {
- x.acos()
-}
-
-fn atan_f32(x: f32) -> f32 {
- x.atan()
-}
-
-fn atan_f64(x: f64) -> f64 {
- x.atan()
-}
-
-fn sinh_f32(x: f32) -> f32 {
- x.sinh()
-}
-
-fn sinh_f64(x: f64) -> f64 {
- x.sinh()
-}
-
-fn cosh_f32(x: f32) -> f32 {
- x.cosh()
-}
-
-fn cosh_f64(x: f64) -> f64 {
- x.cosh()
-}
-
-fn tanh_f32(x: f32) -> f32 {
- x.tanh()
-}
-
-fn tanh_f64(x: f64) -> f64 {
- x.tanh()
-}
-
-fn asinh_f32(x: f32) -> f32 {
- x.asinh()
-}
-
-fn asinh_f64(x: f64) -> f64 {
- x.asinh()
-}
-
-fn acosh_f32(x: f32) -> f32 {
- x.acosh()
-}
-
-fn acosh_f64(x: f64) -> f64 {
- x.acosh()
-}
-
-fn atanh_f32(x: f32) -> f32 {
- x.atanh()
-}
-
-fn atanh_f64(x: f64) -> f64 {
- x.atanh()
-}
-
-fn erf_f32(x: f32) -> f32 {
- libm::erff(x)
-}
-
-fn erf_f64(x: f64) -> f64 {
- libm::erf(x)
-}
-
-fn erfc_f32(x: f32) -> f32 {
- libm::erfcf(x)
-}
-
-fn erfc_f64(x: f64) -> f64 {
- libm::erfc(x)
-}
-
-fn gamma_f32(x: f32) -> f32 {
- libm::tgammaf(x)
-}
-
-fn gamma_f64(x: f64) -> f64 {
- libm::tgamma(x)
-}
-
-fn ln_gamma_f32(x: f32) -> f32 {
- libm::lgammaf(x)
-}
-
-fn ln_gamma_f64(x: f64) -> f64 {
- libm::lgamma(x)
-}
-
-fn round_f32_i32(x: f32) -> i32 {
- x.round() as i32
-}
-
-fn round_f64_i32(x: f64) -> i32 {
- x.round() as i32
-}
-
-fn round_f32_i64(x: f32) -> i64 {
- x.round() as i64
-}
-
-fn round_f64_i64(x: f64) -> i64 {
- x.round() as i64
-}
-
-fn frexp_f32(x: f32) -> (f32, i32) {
- libm::frexpf(x)
-}
-
-fn frexp_f64(x: f64) -> (f64, i32) {
- libm::frexp(x)
-}
-
-fn ldexp_f32(x: f32, exp: i32) -> f32 {
- libm::ldexpf(x, exp)
-}
-
-fn ldexp_f64(x: f64, exp: i32) -> f64 {
- libm::ldexp(x, exp)
-}
-
-fn modf_f32(x: f32) -> (f32, f32) {
- libm::modff(x)
-}
-
-fn modf_f64(x: f64) -> (f64, f64) {
- libm::modf(x)
-}
-
-fn logb_f32(x: f32) -> i32 {
- libm::ilogbf(x)
-}
-
-fn logb_f64(x: f64) -> i32 {
- libm::ilogb(x)
-}
-
-fn next_after_f32(from: f32, to: f32) -> f32 {
- libm::nextafterf(from, to)
-}
-
-fn next_after_f64(from: f64, to: f64) -> f64 {
- libm::nextafter(from, to)
-}
-
-fn copy_sign_f32(x: f32, y: f32) -> f32 {
- libm::copysignf(x, y)
-}
-
-fn copy_sign_f64(x: f64, y: f64) -> f64 {
- libm::copysign(x, y)
-}
-
-pub fn library(manager: &mut ScriptManager) -> Option<()> {
- manager.add_library_function(LIBRARY_NAME, "abs", abs_i32)?;
- manager.add_library_function(LIBRARY_NAME, "labs", abs_i64)?;
- manager.add_library_function(LIBRARY_NAME, "modf", mod_f32)?;
- manager.add_library_function(LIBRARY_NAME, "mod", mod_f64)?;
- manager.add_library_function(LIBRARY_NAME, "remf", remainder_f32)?;
- manager.add_library_function(LIBRARY_NAME, "rem", remainder_f64)?;
- manager.add_library_function(LIBRARY_NAME, "fmaf", mul_add_f32)?;
- manager.add_library_function(LIBRARY_NAME, "fma", mul_add_f64)?;
- manager.add_library_function(LIBRARY_NAME, "fdimf", fdim_f32)?;
- manager.add_library_function(LIBRARY_NAME, "fdim", fdim_f64)?;
- manager.add_library_function(LIBRARY_NAME, "expf", exp_f32)?;
- manager.add_library_function(LIBRARY_NAME, "exp", exp_f64)?;
- manager.add_library_function(LIBRARY_NAME, "exp2f", exp2_f32)?;
- manager.add_library_function(LIBRARY_NAME, "exp2", exp2_f64)?;
- manager.add_library_function(LIBRARY_NAME, "expm1f", expm1_f32)?;
- manager.add_library_function(LIBRARY_NAME, "expm1", expm1_f64)?;
- manager.add_library_function(LIBRARY_NAME, "lnf", ln_f32)?;
- manager.add_library_function(LIBRARY_NAME, "ln", ln_f64)?;
- manager.add_library_function(LIBRARY_NAME, "log2f", log2_f32)?;
- manager.add_library_function(LIBRARY_NAME, "log2", log2_f64)?;
- manager.add_library_function(LIBRARY_NAME, "log10f", log10_f32)?;
- manager.add_library_function(LIBRARY_NAME, "log10", log10_f64)?;
- manager.add_library_function(LIBRARY_NAME, "ln1pf", ln1p_f32)?;
- manager.add_library_function(LIBRARY_NAME, "ln1p", ln1p_f64)?;
- manager.add_library_function(LIBRARY_NAME, "powf", pow_f32)?;
- manager.add_library_function(LIBRARY_NAME, "pow", pow_f64)?;
- manager.add_library_function(LIBRARY_NAME, "cbrtf", cbrt_f32)?;
- manager.add_library_function(LIBRARY_NAME, "cbrt", cbrt_f64)?;
- manager.add_library_function(LIBRARY_NAME, "hypotf", hypotenuse_f32)?;
- manager.add_library_function(LIBRARY_NAME, "hypot", hypotenuse_f64)?;
- manager.add_library_function(LIBRARY_NAME, "sinf", sin_f32)?;
- manager.add_library_function(LIBRARY_NAME, "sin", sin_f64)?;
- manager.add_library_function(LIBRARY_NAME, "cosf", cos_f32)?;
- manager.add_library_function(LIBRARY_NAME, "cos", cos_f64)?;
- manager.add_library_function(LIBRARY_NAME, "tanf", tan_f32)?;
- manager.add_library_function(LIBRARY_NAME, "tan", tan_f64)?;
- manager.add_library_function(LIBRARY_NAME, "asinf", asin_f32)?;
- manager.add_library_function(LIBRARY_NAME, "asin", asin_f64)?;
- manager.add_library_function(LIBRARY_NAME, "acosf", acos_f32)?;
- manager.add_library_function(LIBRARY_NAME, "acos", acos_f64)?;
- manager.add_library_function(LIBRARY_NAME, "atanf", atan_f32)?;
- manager.add_library_function(LIBRARY_NAME, "atan", atan_f64)?;
- manager.add_library_function(LIBRARY_NAME, "sinhf", sinh_f32)?;
- manager.add_library_function(LIBRARY_NAME, "sinh", sinh_f64)?;
- manager.add_library_function(LIBRARY_NAME, "coshf", cosh_f32)?;
- manager.add_library_function(LIBRARY_NAME, "cosh", cosh_f64)?;
- manager.add_library_function(LIBRARY_NAME, "tanhf", tanh_f32)?;
- manager.add_library_function(LIBRARY_NAME, "tanh", tanh_f64)?;
- manager.add_library_function(LIBRARY_NAME, "asinhf", asinh_f32)?;
- manager.add_library_function(LIBRARY_NAME, "asinh", asinh_f64)?;
- manager.add_library_function(LIBRARY_NAME, "acoshf", acosh_f32)?;
- manager.add_library_function(LIBRARY_NAME, "acosh", acosh_f64)?;
- manager.add_library_function(LIBRARY_NAME, "atanhf", atanh_f32)?;
- manager.add_library_function(LIBRARY_NAME, "atanh", atanh_f64)?;
- manager.add_library_function(LIBRARY_NAME, "erff", erf_f32)?;
- manager.add_library_function(LIBRARY_NAME, "erf", erf_f64)?;
- manager.add_library_function(LIBRARY_NAME, "erfcf", erfc_f32)?;
- manager.add_library_function(LIBRARY_NAME, "erfc", erfc_f64)?;
- manager.add_library_function(LIBRARY_NAME, "gammaf", gamma_f32)?;
- manager.add_library_function(LIBRARY_NAME, "gamma", gamma_f64)?;
- manager.add_library_function(LIBRARY_NAME, "lgammaf", ln_gamma_f32)?;
- manager.add_library_function(LIBRARY_NAME, "lgamma", ln_gamma_f64)?;
- manager.add_library_function(LIBRARY_NAME, "lroundf", round_f32_i32)?;
- manager.add_library_function(LIBRARY_NAME, "lround", round_f64_i32)?;
- manager.add_library_function(LIBRARY_NAME, "llroundf", round_f32_i64)?;
- manager.add_library_function(LIBRARY_NAME, "llround", round_f64_i64)?;
- manager.add_library_function(LIBRARY_NAME, "frexpf", frexp_f32)?;
- manager.add_library_function(LIBRARY_NAME, "frexp", frexp_f64)?;
- manager.add_library_function(LIBRARY_NAME, "ldexpf", ldexp_f32)?;
- manager.add_library_function(LIBRARY_NAME, "ldexp", ldexp_f64)?;
- manager.add_library_function(LIBRARY_NAME, "modff", modf_f32)?;
- manager.add_library_function(LIBRARY_NAME, "modf", modf_f64)?;
- manager.add_library_function(LIBRARY_NAME, "ilogbf", logb_f32)?;
- manager.add_library_function(LIBRARY_NAME, "ilogb", logb_f64)?;
- manager.add_library_function(LIBRARY_NAME, "nextafterf", next_after_f32)?;
- manager.add_library_function(LIBRARY_NAME, "nextafter", next_after_f64)?;
- manager.add_library_function(LIBRARY_NAME, "copysignf", copy_sign_f32)?;
- manager.add_library_function(LIBRARY_NAME, "copysign", copy_sign_f64)?;
-
- Some(())
-}
+use crate::ScriptManager;
+
+use super::LIBRARY_NAME;
+
+fn abs_i32(n: i32) -> i32 {
+ n.abs()
+}
+
+fn abs_i64(n: i64) -> i64 {
+ n.abs()
+}
+
+fn mod_f32(x: f32, y: f32) -> f32 {
+ libm::fmodf(x, y)
+}
+
+fn mod_f64(x: f64, y: f64) -> f64 {
+ libm::fmod(x, y)
+}
+
+fn remainder_f32(x: f32, y: f32) -> f32 {
+ libm::remainderf(x, y)
+}
+
+fn remainder_f64(x: f64, y: f64) -> f64 {
+ libm::remainder(x, y)
+}
+
+fn mul_add_f32(x: f32, y: f32, z: f32) -> f32 {
+ x.mul_add(y, z)
+}
+
+fn mul_add_f64(x: f64, y: f64, z: f64) -> f64 {
+ x.mul_add(y, z)
+}
+
+fn fdim_f32(x: f32, y: f32) -> f32 {
+ libm::fdimf(x, y)
+}
+
+fn fdim_f64(x: f64, y: f64) -> f64 {
+ libm::fdim(x, y)
+}
+
+fn exp_f32(x: f32) -> f32 {
+ x.exp()
+}
+
+fn exp_f64(x: f64) -> f64 {
+ x.exp()
+}
+
+fn exp2_f32(x: f32) -> f32 {
+ x.exp2()
+}
+
+fn exp2_f64(x: f64) -> f64 {
+ x.exp2()
+}
+
+fn expm1_f32(x: f32) -> f32 {
+ x.exp_m1()
+}
+
+fn expm1_f64(x: f64) -> f64 {
+ x.exp_m1()
+}
+
+fn ln_f32(x: f32) -> f32 {
+ x.ln()
+}
+
+fn ln_f64(x: f64) -> f64 {
+ x.ln()
+}
+
+fn log10_f32(x: f32) -> f32 {
+ x.log10()
+}
+
+fn log10_f64(x: f64) -> f64 {
+ x.log10()
+}
+
+fn log2_f32(x: f32) -> f32 {
+ x.log2()
+}
+
+fn log2_f64(x: f64) -> f64 {
+ x.log2()
+}
+
+fn ln1p_f32(x: f32) -> f32 {
+ x.ln_1p()
+}
+
+fn ln1p_f64(x: f64) -> f64 {
+ x.ln_1p()
+}
+
+fn pow_f32(base: f32, exponent: f32) -> f32 {
+ base.powf(exponent)
+}
+
+fn pow_f64(base: f64, exponent: f64) -> f64 {
+ base.powf(exponent)
+}
+
+fn cbrt_f32(x: f32) -> f32 {
+ x.cbrt()
+}
+
+fn cbrt_f64(x: f64) -> f64 {
+ x.cbrt()
+}
+
+fn hypotenuse_f32(x: f32, y: f32) -> f32 {
+ x.hypot(y)
+}
+
+fn hypotenuse_f64(x: f64, y: f64) -> f64 {
+ x.hypot(y)
+}
+
+fn sin_f32(x: f32) -> f32 {
+ x.sin()
+}
+
+fn sin_f64(x: f64) -> f64 {
+ x.sin()
+}
+
+fn cos_f32(x: f32) -> f32 {
+ x.cos()
+}
+
+fn cos_f64(x: f64) -> f64 {
+ x.cos()
+}
+
+fn tan_f32(x: f32) -> f32 {
+ x.tan()
+}
+
+fn tan_f64(x: f64) -> f64 {
+ x.tan()
+}
+
+fn asin_f32(x: f32) -> f32 {
+ x.asin()
+}
+
+fn asin_f64(x: f64) -> f64 {
+ x.asin()
+}
+
+fn acos_f32(x: f32) -> f32 {
+ x.acos()
+}
+
+fn acos_f64(x: f64) -> f64 {
+ x.acos()
+}
+
+fn atan_f32(x: f32) -> f32 {
+ x.atan()
+}
+
+fn atan_f64(x: f64) -> f64 {
+ x.atan()
+}
+
+fn sinh_f32(x: f32) -> f32 {
+ x.sinh()
+}
+
+fn sinh_f64(x: f64) -> f64 {
+ x.sinh()
+}
+
+fn cosh_f32(x: f32) -> f32 {
+ x.cosh()
+}
+
+fn cosh_f64(x: f64) -> f64 {
+ x.cosh()
+}
+
+fn tanh_f32(x: f32) -> f32 {
+ x.tanh()
+}
+
+fn tanh_f64(x: f64) -> f64 {
+ x.tanh()
+}
+
+fn asinh_f32(x: f32) -> f32 {
+ x.asinh()
+}
+
+fn asinh_f64(x: f64) -> f64 {
+ x.asinh()
+}
+
+fn acosh_f32(x: f32) -> f32 {
+ x.acosh()
+}
+
+fn acosh_f64(x: f64) -> f64 {
+ x.acosh()
+}
+
+fn atanh_f32(x: f32) -> f32 {
+ x.atanh()
+}
+
+fn atanh_f64(x: f64) -> f64 {
+ x.atanh()
+}
+
+fn erf_f32(x: f32) -> f32 {
+ libm::erff(x)
+}
+
+fn erf_f64(x: f64) -> f64 {
+ libm::erf(x)
+}
+
+fn erfc_f32(x: f32) -> f32 {
+ libm::erfcf(x)
+}
+
+fn erfc_f64(x: f64) -> f64 {
+ libm::erfc(x)
+}
+
+fn gamma_f32(x: f32) -> f32 {
+ libm::tgammaf(x)
+}
+
+fn gamma_f64(x: f64) -> f64 {
+ libm::tgamma(x)
+}
+
+fn ln_gamma_f32(x: f32) -> f32 {
+ libm::lgammaf(x)
+}
+
+fn ln_gamma_f64(x: f64) -> f64 {
+ libm::lgamma(x)
+}
+
+fn round_f32_i32(x: f32) -> i32 {
+ x.round() as i32
+}
+
+fn round_f64_i32(x: f64) -> i32 {
+ x.round() as i32
+}
+
+fn round_f32_i64(x: f32) -> i64 {
+ x.round() as i64
+}
+
+fn round_f64_i64(x: f64) -> i64 {
+ x.round() as i64
+}
+
+fn frexp_f32(x: f32) -> (f32, i32) {
+ libm::frexpf(x)
+}
+
+fn frexp_f64(x: f64) -> (f64, i32) {
+ libm::frexp(x)
+}
+
+fn ldexp_f32(x: f32, exp: i32) -> f32 {
+ libm::ldexpf(x, exp)
+}
+
+fn ldexp_f64(x: f64, exp: i32) -> f64 {
+ libm::ldexp(x, exp)
+}
+
+fn modf_f32(x: f32) -> (f32, f32) {
+ libm::modff(x)
+}
+
+fn modf_f64(x: f64) -> (f64, f64) {
+ libm::modf(x)
+}
+
+fn logb_f32(x: f32) -> i32 {
+ libm::ilogbf(x)
+}
+
+fn logb_f64(x: f64) -> i32 {
+ libm::ilogb(x)
+}
+
+fn next_after_f32(from: f32, to: f32) -> f32 {
+ libm::nextafterf(from, to)
+}
+
+fn next_after_f64(from: f64, to: f64) -> f64 {
+ libm::nextafter(from, to)
+}
+
+fn copy_sign_f32(x: f32, y: f32) -> f32 {
+ libm::copysignf(x, y)
+}
+
+fn copy_sign_f64(x: f64, y: f64) -> f64 {
+ libm::copysign(x, y)
+}
+
+pub fn library(manager: &mut ScriptManager) -> Option<()> {
+ manager.add_library_function(LIBRARY_NAME, "abs", abs_i32)?;
+ manager.add_library_function(LIBRARY_NAME, "labs", abs_i64)?;
+ manager.add_library_function(LIBRARY_NAME, "modf", mod_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "mod", mod_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "remf", remainder_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "rem", remainder_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "fmaf", mul_add_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "fma", mul_add_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "fdimf", fdim_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "fdim", fdim_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "expf", exp_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "exp", exp_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "exp2f", exp2_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "exp2", exp2_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "expm1f", expm1_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "expm1", expm1_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "lnf", ln_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "ln", ln_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "log2f", log2_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "log2", log2_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "log10f", log10_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "log10", log10_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "ln1pf", ln1p_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "ln1p", ln1p_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "powf", pow_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "pow", pow_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "cbrtf", cbrt_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "cbrt", cbrt_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "hypotf", hypotenuse_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "hypot", hypotenuse_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "sinf", sin_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "sin", sin_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "cosf", cos_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "cos", cos_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "tanf", tan_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "tan", tan_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "asinf", asin_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "asin", asin_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "acosf", acos_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "acos", acos_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "atanf", atan_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "atan", atan_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "sinhf", sinh_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "sinh", sinh_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "coshf", cosh_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "cosh", cosh_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "tanhf", tanh_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "tanh", tanh_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "asinhf", asinh_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "asinh", asinh_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "acoshf", acosh_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "acosh", acosh_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "atanhf", atanh_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "atanh", atanh_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "erff", erf_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "erf", erf_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "erfcf", erfc_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "erfc", erfc_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "gammaf", gamma_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "gamma", gamma_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "lgammaf", ln_gamma_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "lgamma", ln_gamma_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "lroundf", round_f32_i32)?;
+ manager.add_library_function(LIBRARY_NAME, "lround", round_f64_i32)?;
+ manager.add_library_function(LIBRARY_NAME, "llroundf", round_f32_i64)?;
+ manager.add_library_function(LIBRARY_NAME, "llround", round_f64_i64)?;
+ manager.add_library_function(LIBRARY_NAME, "frexpf", frexp_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "frexp", frexp_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "ldexpf", ldexp_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "ldexp", ldexp_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "modff", modf_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "modf", modf_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "ilogbf", logb_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "ilogb", logb_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "nextafterf", next_after_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "nextafter", next_after_f64)?;
+ manager.add_library_function(LIBRARY_NAME, "copysignf", copy_sign_f32)?;
+ manager.add_library_function(LIBRARY_NAME, "copysign", copy_sign_f64)?;
+
+ Some(())
+}
diff --git a/scripts/src/libs/mod.rs b/scripts/src/libs/mod.rs
index c6b1ffc..b77a0e2 100644
--- a/scripts/src/libs/mod.rs
+++ b/scripts/src/libs/mod.rs
@@ -1,19 +1,19 @@
-use crate::ScriptManager;
-
-mod allocate;
-mod buffer;
-mod ctype;
-mod math;
-mod system;
-
-const LIBRARY_NAME: &str = "alligator";
-
-pub fn add_alligator_library(manager: &mut ScriptManager) -> Option<()> {
- allocate::library(manager)?;
- buffer::library(manager)?;
- ctype::library(manager)?;
- math::library(manager)?;
- system::library(manager)?;
-
- Some(())
-}
+use crate::ScriptManager;
+
+mod allocate;
+mod buffer;
+mod ctype;
+mod math;
+mod system;
+
+const LIBRARY_NAME: &str = "alligator";
+
+pub fn add_alligator_library(manager: &mut ScriptManager) -> Option<()> {
+ allocate::library(manager)?;
+ buffer::library(manager)?;
+ ctype::library(manager)?;
+ math::library(manager)?;
+ system::library(manager)?;
+
+ Some(())
+}
diff --git a/scripts/src/libs/system.rs b/scripts/src/libs/system.rs
index 9c5a50c..4c7455b 100644
--- a/scripts/src/libs/system.rs
+++ b/scripts/src/libs/system.rs
@@ -1,154 +1,154 @@
-use std::borrow::Cow;
-use std::mem::align_of;
-
-use chrono::Offset;
-use wasmtime::{Caller, Memory};
-
-use crate::{ScriptManager, WasmScriptState};
-
-use super::LIBRARY_NAME;
-
-pub fn _get_memory<'a>(caller: &'a mut Caller<WasmScriptState>) -> (Memory, &'a mut [u8]) {
- let memory = caller.get_export("memory").unwrap().into_memory().unwrap();
- let mem_ptr = memory.data_mut(caller);
- (memory, mem_ptr)
-}
-
-fn _get_string<'a>(
- caller: &'a mut Caller<WasmScriptState>,
- offset: u32,
- length: u32,
-) -> Option<Cow<'a, str>> {
- let (_, mem_ptr) = _get_memory(caller);
- if (offset as usize + length as usize) > mem_ptr.len() {
- return None;
- }
-
- Some(String::from_utf8_lossy(
- &mem_ptr[offset as usize..length as usize],
- ))
-}
-
-fn _log(caller: &mut Caller<WasmScriptState>, level: log::Level, message: u32, length: u32) -> u32 {
- let Some(message) = _get_string(caller, message, length) else {
- return 4;
- };
- log::log!(level, "{}", message);
- 0
-}
-
-pub fn _alloc<'a>(
- mut caller: &'a mut Caller<WasmScriptState>,
- size: u32,
- align: u32,
-) -> Option<(u32, &'a mut [u8])> {
- // find bumper location in memory
- let bump_offset = caller.data().bump_pointer;
- let (memory, memory_ptr) = _get_memory(caller);
- let bump_ptr = &memory_ptr[bump_offset as usize..];
-
- // calculate pointer to the new allocation
- let offset = bump_ptr.as_ptr().align_offset(align as usize);
- let new_offset = bump_offset + offset as u32;
-
- // update bump pointer
- let bump_offset = &mut caller.data_mut().bump_pointer;
- *bump_offset = new_offset + size;
-
- // grow memory if necessary
- let bump_offset = *bump_offset;
- if memory.data_size(&caller) < bump_offset as usize {
- let delta = (size + offset as u32) / (64 * 1024) + 1;
- if memory.grow(&mut caller, delta as u64).is_err() {
- return None;
- }
- }
-
- let new_ptr = &mut _get_memory(caller).1[new_offset as usize..size as usize];
- Some((new_offset, new_ptr))
-}
-
-fn allocate(mut caller: Caller<WasmScriptState>, size: u32, align: u32) -> u32 {
- match _alloc(&mut caller, size, align) {
- Some((ptr, _)) => ptr,
- None => 0,
- }
-}
-
-fn free_sized(mut caller: Caller<'_, WasmScriptState>, ptr: u32, size: u32) -> u32 {
- let bump_offset = &mut caller.data_mut().bump_pointer;
- if ptr + size == *bump_offset {
- *bump_offset = ptr;
- }
-
- 0
-}
-
-fn free_aligned_sized(
- caller: Caller<'_, WasmScriptState>,
- ptr: u32,
- _alignment: u32,
- size: u32,
-) -> u32 {
- free_sized(caller, ptr, size)
-}
-
-fn env_var(mut caller: Caller<'_, WasmScriptState>, name: u32, length: u32) -> u32 {
- let Some(name) = _get_string(&mut caller, name, length) else {
- return 4;
- };
- let Ok(value) = std::env::var(name.to_string()) else {
- return 1;
- };
-
- let Some((offset, ptr)) = _alloc(&mut caller, value.len() as u32, align_of::<u8>() as u32)
- else {
- return 0;
- };
- ptr.clone_from_slice(value.as_bytes());
-
- offset
-}
-
-fn random_number() -> u64 {
- rand::random()
-}
-
-fn current_time_utc() -> (i64, u32) {
- let duration = chrono::Utc::now() - chrono::DateTime::<chrono::Utc>::MIN_UTC;
- (
- duration.num_seconds(),
- duration.to_std().unwrap().subsec_nanos(),
- )
-}
-
-fn local_offset() -> i32 {
- chrono::Local::now().offset().fix().local_minus_utc()
-}
-
-fn log(mut caller: Caller<'_, WasmScriptState>, message: u32, length: u32) {
- _log(&mut caller, log::Level::Info, message, length);
-}
-
-fn log_warn(mut caller: Caller<'_, WasmScriptState>, message: u32, length: u32) {
- _log(&mut caller, log::Level::Warn, message, length);
-}
-
-fn log_error(mut caller: Caller<'_, WasmScriptState>, message: u32, length: u32) {
- _log(&mut caller, log::Level::Error, message, length);
-}
-
-pub fn library(manager: &mut ScriptManager) -> Option<()> {
- manager.add_library_function(LIBRARY_NAME, "aligned_alloc", allocate)?;
- manager.add_library_function(LIBRARY_NAME, "free_sized", free_sized)?;
- manager.add_library_function(LIBRARY_NAME, "free_aligned_sized", free_aligned_sized)?;
- manager.add_library_function(LIBRARY_NAME, "env_var", env_var)?;
- manager.add_library_function(LIBRARY_NAME, "random_number", random_number)?;
- manager.add_library_function(LIBRARY_NAME, "current_time_utc", current_time_utc)?;
- manager.add_library_function(LIBRARY_NAME, "local_offset", local_offset)?;
- manager.add_library_function(LIBRARY_NAME, "log", log)?;
- manager.add_library_function(LIBRARY_NAME, "log_warn", log_warn)?;
- manager.add_library_function(LIBRARY_NAME, "log_error", log_error)?;
-
- Some(())
-}
+use std::borrow::Cow;
+use std::mem::align_of;
+
+use chrono::Offset;
+use wasmtime::{Caller, Memory};
+
+use crate::{ScriptManager, WasmScriptState};
+
+use super::LIBRARY_NAME;
+
+pub fn _get_memory<'a>(caller: &'a mut Caller<WasmScriptState>) -> (Memory, &'a mut [u8]) {
+ let memory = caller.get_export("memory").unwrap().into_memory().unwrap();
+ let mem_ptr = memory.data_mut(caller);
+ (memory, mem_ptr)
+}
+
+fn _get_string<'a>(
+ caller: &'a mut Caller<WasmScriptState>,
+ offset: u32,
+ length: u32,
+) -> Option<Cow<'a, str>> {
+ let (_, mem_ptr) = _get_memory(caller);
+ if (offset as usize + length as usize) > mem_ptr.len() {
+ return None;
+ }
+
+ Some(String::from_utf8_lossy(
+ &mem_ptr[offset as usize..length as usize],
+ ))
+}
+
+fn _log(caller: &mut Caller<WasmScriptState>, level: log::Level, message: u32, length: u32) -> u32 {
+ let Some(message) = _get_string(caller, message, length) else {
+ return 4;
+ };
+ log::log!(level, "{}", message);
+ 0
+}
+
+pub fn _alloc<'a>(
+ mut caller: &'a mut Caller<WasmScriptState>,
+ size: u32,
+ align: u32,
+) -> Option<(u32, &'a mut [u8])> {
+ // find bumper location in memory
+ let bump_offset = caller.data().bump_pointer;
+ let (memory, memory_ptr) = _get_memory(caller);
+ let bump_ptr = &memory_ptr[bump_offset as usize..];
+
+ // calculate pointer to the new allocation
+ let offset = bump_ptr.as_ptr().align_offset(align as usize);
+ let new_offset = bump_offset + offset as u32;
+
+ // update bump pointer
+ let bump_offset = &mut caller.data_mut().bump_pointer;
+ *bump_offset = new_offset + size;
+
+ // grow memory if necessary
+ let bump_offset = *bump_offset;
+ if memory.data_size(&caller) < bump_offset as usize {
+ let delta = (size + offset as u32) / (64 * 1024) + 1;
+ if memory.grow(&mut caller, delta as u64).is_err() {
+ return None;
+ }
+ }
+
+ let new_ptr = &mut _get_memory(caller).1[new_offset as usize..size as usize];
+ Some((new_offset, new_ptr))
+}
+
+fn allocate(mut caller: Caller<WasmScriptState>, size: u32, align: u32) -> u32 {
+ match _alloc(&mut caller, size, align) {
+ Some((ptr, _)) => ptr,
+ None => 0,
+ }
+}
+
+fn free_sized(mut caller: Caller<'_, WasmScriptState>, ptr: u32, size: u32) -> u32 {
+ let bump_offset = &mut caller.data_mut().bump_pointer;
+ if ptr + size == *bump_offset {
+ *bump_offset = ptr;
+ }
+
+ 0
+}
+
+fn free_aligned_sized(
+ caller: Caller<'_, WasmScriptState>,
+ ptr: u32,
+ _alignment: u32,
+ size: u32,
+) -> u32 {
+ free_sized(caller, ptr, size)
+}
+
+fn env_var(mut caller: Caller<'_, WasmScriptState>, name: u32, length: u32) -> u32 {
+ let Some(name) = _get_string(&mut caller, name, length) else {
+ return 4;
+ };
+ let Ok(value) = std::env::var(name.to_string()) else {
+ return 1;
+ };
+
+ let Some((offset, ptr)) = _alloc(&mut caller, value.len() as u32, align_of::<u8>() as u32)
+ else {
+ return 0;
+ };
+ ptr.clone_from_slice(value.as_bytes());
+
+ offset
+}
+
+fn random_number() -> u64 {
+ rand::random()
+}
+
+fn current_time_utc() -> (i64, u32) {
+ let duration = chrono::Utc::now() - chrono::DateTime::<chrono::Utc>::MIN_UTC;
+ (
+ duration.num_seconds(),
+ duration.to_std().unwrap().subsec_nanos(),
+ )
+}
+
+fn local_offset() -> i32 {
+ chrono::Local::now().offset().fix().local_minus_utc()
+}
+
+fn log(mut caller: Caller<'_, WasmScriptState>, message: u32, length: u32) {
+ _log(&mut caller, log::Level::Info, message, length);
+}
+
+fn log_warn(mut caller: Caller<'_, WasmScriptState>, message: u32, length: u32) {
+ _log(&mut caller, log::Level::Warn, message, length);
+}
+
+fn log_error(mut caller: Caller<'_, WasmScriptState>, message: u32, length: u32) {
+ _log(&mut caller, log::Level::Error, message, length);
+}
+
+pub fn library(manager: &mut ScriptManager) -> Option<()> {
+ manager.add_library_function(LIBRARY_NAME, "aligned_alloc", allocate)?;
+ manager.add_library_function(LIBRARY_NAME, "free_sized", free_sized)?;
+ manager.add_library_function(LIBRARY_NAME, "free_aligned_sized", free_aligned_sized)?;
+ manager.add_library_function(LIBRARY_NAME, "env_var", env_var)?;
+ manager.add_library_function(LIBRARY_NAME, "random_number", random_number)?;
+ manager.add_library_function(LIBRARY_NAME, "current_time_utc", current_time_utc)?;
+ manager.add_library_function(LIBRARY_NAME, "local_offset", local_offset)?;
+ manager.add_library_function(LIBRARY_NAME, "log", log)?;
+ manager.add_library_function(LIBRARY_NAME, "log_warn", log_warn)?;
+ manager.add_library_function(LIBRARY_NAME, "log_error", log_error)?;
+
+ Some(())
+}
diff --git a/scripts/src/vtable.rs b/scripts/src/vtable.rs
index 0fbb324..33b71ab 100644
--- a/scripts/src/vtable.rs
+++ b/scripts/src/vtable.rs
@@ -1,10 +1,10 @@
-/// A trait for scripts
-pub trait ScriptTable: Send + Sync {
- /// This is called whenever the script is enabled
- fn begin(&mut self);
-
- /// This is called every frame
- fn update(&mut self);
-}
-
-pub type VTableScript = &'static mut dyn ScriptTable;
+/// A trait for scripts
+pub trait ScriptTable: Send + Sync {
+ /// This is called whenever the script is enabled
+ fn begin(&mut self);
+
+ /// This is called every frame
+ fn update(&mut self);
+}
+
+pub type VTableScript = &'static mut dyn ScriptTable;
diff --git a/scripts/src/wasm.rs b/scripts/src/wasm.rs
index 7ac9dae..06d840f 100644
--- a/scripts/src/wasm.rs
+++ b/scripts/src/wasm.rs
@@ -1,170 +1,170 @@
-use std::path::Path;
-
-use thiserror::Error;
-use wasmtime::{Engine, Instance, Linker, Module, Mutability, Store, ValType};
-
-// It's a bad idea to have the memory allocator return a number that could also
-// indicate an error, so this is set to be at least eight.
-const MIN_BUMP_POINTER: u32 = 8;
-
-/// Information about the script which can be used by functions it calls
-pub struct WasmScriptState {
- pub bump_pointer: u32,
- pub trusted: bool,
-}
-
-impl WasmScriptState {
- pub const fn new(trusted: bool) -> Self {
- Self {
- bump_pointer: MIN_BUMP_POINTER,
- trusted,
- }
- }
-}
-
-/// A script, its path in the filesystem, and some metadata
-pub struct WasmScript {
- path: Box<Path>,
- module: Module,
- store: Store<WasmScriptState>,
- instance: Instance,
- trusted: bool,
- //state: Value,
-}
-
-#[derive(Debug, Error)]
-pub enum InvalidWasmScript {
- #[error("There is no exported memory called 'memory', which is required")]
- NoExportedMemory,
- #[error("The exported symbol, 'memory' must be a memory")]
- MemoryIsNotAMemory,
- #[error("The memory must be 32-bit, not 64-bit")]
- MemoryTooLarge,
- #[error("There is no exported global called '__heap_base', which is required")]
- NoHeapBase,
- #[error("The exported symbol, '__heap_base' must be a constant global")]
- HeapBaseIsNotGlobal,
- #[error("The exported global, '__heap_base' must be an i32")]
- HeapBaseMustBeI32,
- #[error("The exported global, '__heap_base' must be a constant")]
- HeapBaseMustBeConstant,
- #[error("{}", .0)]
- CompilerError(#[from] wasmtime::Error),
-}
-
-/// Confirms that the module can be used as a script
-fn validate_module(module: &Module) -> Result<(), InvalidWasmScript> {
- // verify that memory is exported from this module and is valid
- let Some(export) = module.get_export("memory") else {
- return Err(InvalidWasmScript::NoExportedMemory);
- };
- let Some(memory) = export.memory() else {
- return Err(InvalidWasmScript::MemoryIsNotAMemory);
- };
- if memory.is_64() {
- return Err(InvalidWasmScript::MemoryTooLarge);
- }
-
- // verify __heap_base global
- let Some(export) = module.get_export("__heap_base") else {
- return Err(InvalidWasmScript::NoHeapBase);
- };
- let Some(heap_base) = export.global() else {
- return Err(InvalidWasmScript::HeapBaseIsNotGlobal);
- };
- if *heap_base.content() != ValType::I32 {
- return Err(InvalidWasmScript::HeapBaseMustBeI32);
- }
- if heap_base.mutability() != Mutability::Const {
- return Err(InvalidWasmScript::HeapBaseMustBeConstant);
- }
-
- Ok(())
-}
-
-impl WasmScript {
- pub fn new(
- path: &Path,
- engine: &Engine,
- linker: &Linker<WasmScriptState>,
- trusted: bool,
- ) -> Result<Self, InvalidWasmScript> {
- let module = Module::from_file(engine, path)?;
- validate_module(&module)?;
- let mut store = Store::new(engine, WasmScriptState::new(trusted));
- let instance = linker.instantiate(&mut store, &module)?;
-
- Ok(Self {
- path: path.into(),
- module,
- store,
- instance,
- trusted,
- })
- }
-
- /// Reload from the filesystem
- pub fn reload(
- &mut self,
- engine: &Engine,
- linker: &Linker<WasmScriptState>,
- ) -> Result<(), InvalidWasmScript> {
- let module = Module::from_file(engine, &self.path)?;
- validate_module(&module)?;
- self.store = Store::new(engine, WasmScriptState::new(self.trusted));
- self.instance = linker.instantiate(&mut self.store, &module)?;
-
- Ok(())
- }
-
- /// Re-links the module. This doesn't load the module from the filesystem.
- pub fn relink(
- &mut self,
- engine: &Engine,
- linker: &Linker<WasmScriptState>,
- ) -> Result<(), InvalidWasmScript> {
- self.store = Store::new(engine, WasmScriptState::new(self.trusted));
- self.instance = linker.instantiate(&mut self.store, &self.module)?;
- Ok(())
- }
-
- pub fn is_trusted(&self) -> bool {
- self.trusted
- }
-
- pub fn trust(&mut self) {
- self.trusted = true;
- }
-
- pub fn untrust(&mut self) {
- self.trusted = false;
- }
-
- fn run_function_if_exists(&mut self, name: &str) -> wasmtime::Result<()> {
- // set bump pointer to the start of the heap
- let heap_base = self
- .instance
- .get_global(&mut self.store, "__heap_base")
- .unwrap()
- .get(&mut self.store)
- .unwrap_i32();
- let bump_ptr = &mut self.store.data_mut().bump_pointer;
- *bump_ptr = (heap_base as u32).max(MIN_BUMP_POINTER);
-
- // call the given function
- let func = self.instance.get_func(&mut self.store, name);
- if let Some(func) = func {
- func.call(&mut self.store, &[], &mut [])?;
- }
-
- Ok(())
- }
-
- pub fn begin(&mut self) -> wasmtime::Result<()> {
- self.run_function_if_exists("begin")
- }
-
- pub fn update(&mut self) -> wasmtime::Result<()> {
- self.run_function_if_exists("update")
- }
-}
+use std::path::Path;
+
+use thiserror::Error;
+use wasmtime::{Engine, Instance, Linker, Module, Mutability, Store, ValType};
+
+// It's a bad idea to have the memory allocator return a number that could also
+// indicate an error, so this is set to be at least eight.
+const MIN_BUMP_POINTER: u32 = 8;
+
+/// Information about the script which can be used by functions it calls
+pub struct WasmScriptState {
+ pub bump_pointer: u32,
+ pub trusted: bool,
+}
+
+impl WasmScriptState {
+ pub const fn new(trusted: bool) -> Self {
+ Self {
+ bump_pointer: MIN_BUMP_POINTER,
+ trusted,
+ }
+ }
+}
+
+/// A script, its path in the filesystem, and some metadata
+pub struct WasmScript {
+ path: Box<Path>,
+ module: Module,
+ store: Store<WasmScriptState>,
+ instance: Instance,
+ trusted: bool,
+ //state: Value,
+}
+
+#[derive(Debug, Error)]
+pub enum InvalidWasmScript {
+ #[error("There is no exported memory called 'memory', which is required")]
+ NoExportedMemory,
+ #[error("The exported symbol, 'memory' must be a memory")]
+ MemoryIsNotAMemory,
+ #[error("The memory must be 32-bit, not 64-bit")]
+ MemoryTooLarge,
+ #[error("There is no exported global called '__heap_base', which is required")]
+ NoHeapBase,
+ #[error("The exported symbol, '__heap_base' must be a constant global")]
+ HeapBaseIsNotGlobal,
+ #[error("The exported global, '__heap_base' must be an i32")]
+ HeapBaseMustBeI32,
+ #[error("The exported global, '__heap_base' must be a constant")]
+ HeapBaseMustBeConstant,
+ #[error("{}", .0)]
+ CompilerError(#[from] wasmtime::Error),
+}
+
+/// Confirms that the module can be used as a script
+fn validate_module(module: &Module) -> Result<(), InvalidWasmScript> {
+ // verify that memory is exported from this module and is valid
+ let Some(export) = module.get_export("memory") else {
+ return Err(InvalidWasmScript::NoExportedMemory);
+ };
+ let Some(memory) = export.memory() else {
+ return Err(InvalidWasmScript::MemoryIsNotAMemory);
+ };
+ if memory.is_64() {
+ return Err(InvalidWasmScript::MemoryTooLarge);
+ }
+
+ // verify __heap_base global
+ let Some(export) = module.get_export("__heap_base") else {
+ return Err(InvalidWasmScript::NoHeapBase);
+ };
+ let Some(heap_base) = export.global() else {
+ return Err(InvalidWasmScript::HeapBaseIsNotGlobal);
+ };
+ if *heap_base.content() != ValType::I32 {
+ return Err(InvalidWasmScript::HeapBaseMustBeI32);
+ }
+ if heap_base.mutability() != Mutability::Const {
+ return Err(InvalidWasmScript::HeapBaseMustBeConstant);
+ }
+
+ Ok(())
+}
+
+impl WasmScript {
+ pub fn new(
+ path: &Path,
+ engine: &Engine,
+ linker: &Linker<WasmScriptState>,
+ trusted: bool,
+ ) -> Result<Self, InvalidWasmScript> {
+ let module = Module::from_file(engine, path)?;
+ validate_module(&module)?;
+ let mut store = Store::new(engine, WasmScriptState::new(trusted));
+ let instance = linker.instantiate(&mut store, &module)?;
+
+ Ok(Self {
+ path: path.into(),
+ module,
+ store,
+ instance,
+ trusted,
+ })
+ }
+
+ /// Reload from the filesystem
+ pub fn reload(
+ &mut self,
+ engine: &Engine,
+ linker: &Linker<WasmScriptState>,
+ ) -> Result<(), InvalidWasmScript> {
+ let module = Module::from_file(engine, &self.path)?;
+ validate_module(&module)?;
+ self.store = Store::new(engine, WasmScriptState::new(self.trusted));
+ self.instance = linker.instantiate(&mut self.store, &module)?;
+
+ Ok(())
+ }
+
+ /// Re-links the module. This doesn't load the module from the filesystem.
+ pub fn relink(
+ &mut self,
+ engine: &Engine,
+ linker: &Linker<WasmScriptState>,
+ ) -> Result<(), InvalidWasmScript> {
+ self.store = Store::new(engine, WasmScriptState::new(self.trusted));
+ self.instance = linker.instantiate(&mut self.store, &self.module)?;
+ Ok(())
+ }
+
+ pub fn is_trusted(&self) -> bool {
+ self.trusted
+ }
+
+ pub fn trust(&mut self) {
+ self.trusted = true;
+ }
+
+ pub fn untrust(&mut self) {
+ self.trusted = false;
+ }
+
+ fn run_function_if_exists(&mut self, name: &str) -> wasmtime::Result<()> {
+ // set bump pointer to the start of the heap
+ let heap_base = self
+ .instance
+ .get_global(&mut self.store, "__heap_base")
+ .unwrap()
+ .get(&mut self.store)
+ .unwrap_i32();
+ let bump_ptr = &mut self.store.data_mut().bump_pointer;
+ *bump_ptr = (heap_base as u32).max(MIN_BUMP_POINTER);
+
+ // call the given function
+ let func = self.instance.get_func(&mut self.store, name);
+ if let Some(func) = func {
+ func.call(&mut self.store, &[], &mut [])?;
+ }
+
+ Ok(())
+ }
+
+ pub fn begin(&mut self) -> wasmtime::Result<()> {
+ self.run_function_if_exists("begin")
+ }
+
+ pub fn update(&mut self) -> wasmtime::Result<()> {
+ self.run_function_if_exists("update")
+ }
+}
diff --git a/shell-spec.txt b/shell-spec.txt
index dda23c7..d0238fd 100644
--- a/shell-spec.txt
+++ b/shell-spec.txt
@@ -1,13 +1,16 @@
-# Alligator Shell Specification
-
-Default Port Number: 26009
-Using TCP Protocol
-
-## Runtime to Editor
-
-runtimelog [trace|debug|info|warn|error] FILE:LINE MSG
-scriptlog [trace|debug|info|warn|error] FILE:LINE MSG
-
-## Editor to Runtime
-
-stop
+# Alligator Shell Specification
+
+Default Port Number: 26009
+Using TCP Protocol
+
+## Runtime to Editor
+
+runtimelog [trace|debug|info|warn|error] FILE:LINE MSG
+scriptlog [trace|debug|info|warn|error] FILE:LINE MSG
+frametime UNIX_MICROSECONDS
+scopestart SCOPENAME UNIX_MICROSECONDS
+scopeend UNIX_MICROSECONDS
+
+## Editor to Runtime
+
+stop
diff --git a/src/main.rs b/src/main.rs
index ade657e..c8d4618 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,145 +1,154 @@
-use std::collections::HashMap;
-use std::fs::File;
-use std::io::Read;
-use std::num::NonZeroU32;
-use std::path::Path;
-
-use alligator_scripts::ScriptManager;
-use alligator_sprites::SpriteManager;
-use alligator_sys::{Renderer, RendererConfig, Window, WindowConfig, WindowEvent};
-
-use serde::Deserialize;
-use sha3::{Digest, Sha3_256};
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
-enum ScriptType {
- Wasm,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
-enum ConfigWindowMode {
- Windowed,
- BorderlessFullscreen,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-struct ConfigScript {
- path: Box<Path>,
- script_type: ScriptType,
- hash: Option<String>,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-struct ConfigSprite {
- texture: String,
- x: f32,
- y: f32,
- z: f32,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-struct ConfigTexture {
- size: usize,
- path: Box<Path>,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-struct Scene {
- initial_sprites: HashMap<String, ConfigSprite>,
- initial_scripts: Vec<String>,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-pub struct Config {
- alligator_version: usize,
- scenes: HashMap<String, Scene>,
- textures: HashMap<String, ConfigTexture>,
- scripts: HashMap<String, ConfigScript>,
- default_scene: String,
- sprite_manager_capacity: u32,
- default_window_width: NonZeroU32,
- default_window_height: NonZeroU32,
- default_window_mode: ConfigWindowMode,
- window_title: String,
- vsync: bool,
-}
-
-fn sprite_manager(config: &Config) -> SpriteManager {
- SpriteManager::with_capacity(config.sprite_manager_capacity as usize)
-}
-
-fn script_manager(config: &Config) -> ScriptManager {
- let mut scripts = ScriptManager::new();
- for (key, script) in config.scripts.iter() {
- let path = script.path.clone();
- let trusted = if let Some(hash) = &script.hash {
- let mut bytes = Vec::new();
- let mut msg = File::open(&path).unwrap();
- msg.read_to_end(&mut bytes).unwrap();
- let mut hasher = Sha3_256::new();
- hasher.update(bytes);
- let result = hasher.finalize();
- hash.as_bytes() == &result[..]
- } else {
- false
- };
-
- scripts
- .add_wasm_script(key.clone().into_boxed_str(), path, trusted)
- .unwrap();
- }
-
- scripts
-}
-
-fn window(config: &Config) -> Window {
- let config = WindowConfig {
- title: config.window_title.clone(),
- default_width: config.default_window_width.get(),
- default_height: config.default_window_height.get(),
- default_x: 100,
- default_y: 100,
- borderless_fullscreen: config.default_window_mode == ConfigWindowMode::BorderlessFullscreen,
- visible: false,
- };
-
- Window::new(config)
-}
-
-fn renderer(config: &Config, window: &Window) -> Renderer {
- let config = RendererConfig {
- width: config.default_window_width.get(),
- height: config.default_window_height.get(),
- instance_capacity: config.sprite_manager_capacity,
- fullscreen: false,
- vsync: config.vsync,
- };
-
- Renderer::new(window, config)
-}
-
-fn main() {
- std::env::set_current_dir(std::env::current_exe().unwrap().parent().unwrap()).unwrap();
- let config = File::open("game.json").unwrap();
- let config: Config = serde_json::from_reader(config).unwrap();
-
- let sprites = sprite_manager(&config);
- let scripts = script_manager(&config);
- let mut window = window(&config);
-
- window.wait_for_resume();
-
- let mut renderer = renderer(&config, &window);
- window.set_visible(true);
-
- window.run(move |window, event| match event {
- Some(WindowEvent::RedrawRequest) => {
- renderer.render_frame();
- }
- Some(WindowEvent::CloseRequest) => {
- std::process::exit(0);
- }
- Some(_) => (),
- None => window.request_redraw(),
- })
-}
+use std::collections::HashMap;
+use std::fs::File;
+use std::io::Read;
+use std::num::NonZeroU32;
+use std::path::Path;
+
+use alligator_console::Console;
+use alligator_profiler as profile;
+use alligator_scripts::ScriptManager;
+use alligator_sprites::SpriteManager;
+use alligator_sys::{Renderer, RendererConfig, Window, WindowConfig, WindowEvent};
+
+use pollster::FutureExt;
+use serde::Deserialize;
+use sha3::{Digest, Sha3_256};
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+enum ScriptType {
+ Wasm,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+enum ConfigWindowMode {
+ Windowed,
+ BorderlessFullscreen,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+struct ConfigScript {
+ path: Box<Path>,
+ script_type: ScriptType,
+ hash: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+struct ConfigSprite {
+ texture: String,
+ x: f32,
+ y: f32,
+ z: f32,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+struct ConfigTexture {
+ size: usize,
+ path: Box<Path>,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+struct Scene {
+ initial_sprites: HashMap<String, ConfigSprite>,
+ initial_scripts: Vec<String>,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+pub struct Config {
+ alligator_version: String,
+ scenes: HashMap<String, Scene>,
+ textures: HashMap<String, ConfigTexture>,
+ scripts: HashMap<String, ConfigScript>,
+ default_scene: String,
+ sprite_manager_capacity: u32,
+ default_window_width: Option<NonZeroU32>,
+ default_window_height: Option<NonZeroU32>,
+ default_window_mode: ConfigWindowMode,
+ window_title: String,
+ vsync: bool,
+}
+
+fn sprite_manager(config: &Config) -> SpriteManager {
+ SpriteManager::with_capacity(config.sprite_manager_capacity as usize)
+}
+
+fn script_manager(config: &Config) -> ScriptManager {
+ let mut scripts = ScriptManager::new();
+ for (key, script) in config.scripts.iter() {
+ let path = script.path.clone();
+ let trusted = if let Some(hash) = &script.hash {
+ let mut bytes = Vec::new();
+ let mut msg = File::open(&path).unwrap();
+ msg.read_to_end(&mut bytes).unwrap();
+ let mut hasher = Sha3_256::new();
+ hasher.update(bytes);
+ let result = hasher.finalize();
+ hash.as_bytes() == &result[..]
+ } else {
+ false
+ };
+
+ scripts
+ .add_wasm_script(key.clone().into_boxed_str(), path, trusted)
+ .unwrap();
+ }
+
+ scripts
+}
+
+fn window(config: &Config) -> Window {
+ let config = WindowConfig {
+ title: config.window_title.clone(),
+ default_width: config.default_window_width.get(),
+ default_height: config.default_window_height.get(),
+ default_x: 100,
+ default_y: 100,
+ borderless_fullscreen: config.default_window_mode == ConfigWindowMode::BorderlessFullscreen,
+ visible: false,
+ };
+
+ Window::new(config)
+}
+
+fn renderer(config: &Config, window: &Window) -> Renderer {
+ let config = RendererConfig {
+ width: config.default_window_width.get(),
+ height: config.default_window_height.get(),
+ instance_capacity: config.sprite_manager_capacity,
+ fullscreen: false,
+ vsync: config.vsync,
+ };
+
+ Renderer::new(window, config)
+}
+
+fn main() {
+ let console = Console::new(26009)
+ .block_on()
+ .expect("The console should not fail to start");
+ profile::set_profiler(console.logger());
+
+ std::env::set_current_dir(std::env::current_exe().unwrap().parent().unwrap()).unwrap();
+ let config = File::open("game.json").unwrap();
+ let config: Config = serde_json::from_reader(config).unwrap();
+
+ let sprites = sprite_manager(&config);
+ let scripts = script_manager(&config);
+ let mut window = window(&config);
+
+ window.wait_for_resume();
+
+ let mut renderer = renderer(&config, &window);
+ window.set_visible(true);
+
+ window.run(move |window, event| match event {
+ Some(WindowEvent::RedrawRequest) => {
+ renderer.render_frame();
+ profile::finish_frame();
+ }
+ Some(WindowEvent::CloseRequest) => {
+ std::process::exit(0);
+ }
+ Some(_) => (),
+ None => window.request_redraw(),
+ })
+}
diff --git a/sys/alligator_backend.lib b/sys/alligator_backend.lib
new file mode 100644
index 0000000..1b79670
--- /dev/null
+++ b/sys/alligator_backend.lib
Binary files differ
diff --git a/sys/build.rs b/sys/build.rs
index c33a20f..8efc265 100644
--- a/sys/build.rs
+++ b/sys/build.rs
@@ -1,8 +1,8 @@
-fn main() {
- let out_dir = std::env::var("OUT_DIR").unwrap();
- eprintln!("{out_dir}");
- println!("cargo:rustc-link-lib=d3d11");
- println!("cargo:rustc-link-search=native=./");
- println!("cargo:rustc-link-lib-static=alligator_backend");
- println!("cargo:rerun-if-changed=alligator_backend.lib");
-}
+fn main() {
+ let out_dir = std::env::var("OUT_DIR").unwrap();
+ eprintln!("{out_dir}");
+ println!("cargo:rustc-link-lib=d3d11");
+ println!("cargo:rustc-link-search=native=./");
+ println!("cargo:rustc-link-lib-static=alligator_backend");
+ println!("cargo:rerun-if-changed=alligator_backend.lib");
+}
diff --git a/sys/src/renderer.rs b/sys/src/renderer.rs
index 05d111b..a4dab20 100644
--- a/sys/src/renderer.rs
+++ b/sys/src/renderer.rs
@@ -1,49 +1,49 @@
-use crate::{RendererConfig, Vertex, Window};
-
-pub struct Renderer {
- ptr: *mut (),
-}
-
-impl Drop for Renderer {
- fn drop(&mut self) {
- unsafe { crate::destroy_renderer(self.ptr) }
- }
-}
-
-impl Renderer {
- pub fn new(window: &Window, config: RendererConfig) -> Self {
- let ptr = unsafe { crate::new_renderer(config, window.ptr) };
- Self { ptr }
- }
-
- pub fn resize(&mut self, width: u32, height: u32) {
- unsafe { crate::resize_renderer(self.ptr, width, height) }
- }
-
- pub fn set_vsync(&mut self, vsync: bool) {
- unsafe { crate::set_vsync(self.ptr, vsync) }
- }
-
- pub fn create_vertex_buffer(&mut self, vertices: &[Vertex]) {
- assert!(vertices.len() < (u32::MAX as usize), "Too many triangles!");
- let ptr = vertices.as_ptr();
- let len = vertices.len();
- unsafe { crate::create_vertex_buffer(self.ptr, len as u32, ptr) }
- }
-
- pub fn set_camera(
- &mut self,
- x: f32,
- y: f32,
- zoom: f32,
- rotation: f32,
- width: f32,
- height: f32,
- ) {
- unsafe { crate::set_camera(self.ptr, x, y, zoom, rotation, width, height) }
- }
-
- pub fn render_frame(&mut self) {
- unsafe { crate::render_frame(self.ptr) }
- }
-}
+use crate::{RendererConfig, Vertex, Window};
+
+pub struct Renderer {
+ ptr: *mut (),
+}
+
+impl Drop for Renderer {
+ fn drop(&mut self) {
+ unsafe { crate::destroy_renderer(self.ptr) }
+ }
+}
+
+impl Renderer {
+ pub fn new(window: &Window, config: RendererConfig) -> Self {
+ let ptr = unsafe { crate::new_renderer(config, window.ptr) };
+ Self { ptr }
+ }
+
+ pub fn resize(&mut self, width: u32, height: u32) {
+ unsafe { crate::resize_renderer(self.ptr, width, height) }
+ }
+
+ pub fn set_vsync(&mut self, vsync: bool) {
+ unsafe { crate::set_vsync(self.ptr, vsync) }
+ }
+
+ pub fn create_vertex_buffer(&mut self, vertices: &[Vertex]) {
+ assert!(vertices.len() < (u32::MAX as usize), "Too many triangles!");
+ let ptr = vertices.as_ptr();
+ let len = vertices.len();
+ unsafe { crate::create_vertex_buffer(self.ptr, len as u32, ptr) }
+ }
+
+ pub fn set_camera(
+ &mut self,
+ x: f32,
+ y: f32,
+ zoom: f32,
+ rotation: f32,
+ width: f32,
+ height: f32,
+ ) {
+ unsafe { crate::set_camera(self.ptr, x, y, zoom, rotation, width, height) }
+ }
+
+ pub fn render_frame(&mut self) {
+ unsafe { crate::render_frame(self.ptr) }
+ }
+}
diff --git a/sys/src/window.rs b/sys/src/window.rs
index 19de5e7..f9a8832 100644
--- a/sys/src/window.rs
+++ b/sys/src/window.rs
@@ -1,116 +1,116 @@
-use std::ffi::{c_void, CString};
-use std::ops::ControlFlow;
-
-use crate::{CWindowConfig, CWindowEvent};
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct WindowConfig {
- pub title: String,
- pub default_width: u32,
- pub default_height: u32,
- pub default_x: u32,
- pub default_y: u32,
- pub visible: bool,
- pub borderless_fullscreen: bool,
-}
-
-pub struct Window {
- pub(crate) ptr: *mut (),
-}
-
-pub enum WindowEvent {
- Other = 1,
- CloseRequest,
- ScaleFactorChange,
- Resume,
- RedrawRequest,
-}
-
-impl Drop for Window {
- fn drop(&mut self) {
- unsafe { crate::destroy_window(self.ptr) }
- }
-}
-
-impl Window {
- pub fn new(config: WindowConfig) -> Self {
- let title = CString::new(config.title.as_bytes()).unwrap();
- let config = CWindowConfig {
- default_width: config.default_width,
- default_height: config.default_height,
- default_x: config.default_x,
- default_y: config.default_y,
- visible: config.visible,
- borderless_fullscreen: config.borderless_fullscreen,
- title: title.as_ptr(),
- };
-
- let window = unsafe { crate::create_window(config) };
-
- Self { ptr: window }
- }
-
- pub fn set_visible(&mut self, visible: bool) {
- unsafe { crate::set_visible(self.ptr, visible) }
- }
-
- pub fn set_title(&mut self, title: &str) {
- let string = CString::new(title.to_string().as_bytes()).unwrap();
- let bytes = string.as_ptr();
- unsafe { crate::set_title(self.ptr, bytes) }
- }
-
- pub fn resize(&mut self, width: u32, height: u32) {
- unsafe { crate::resize_window(self.ptr, width, height) }
- }
-
- pub fn set_fullscreen(&mut self, fullscreen: bool) {
- unsafe { crate::set_fullscreen(self.ptr, fullscreen) }
- }
-
- fn translate_event(event: CWindowEvent) -> Option<WindowEvent> {
- let event = match event {
- CWindowEvent::AboutToWait => return None,
- CWindowEvent::Other => WindowEvent::Other,
- CWindowEvent::CloseRequest => WindowEvent::CloseRequest,
- CWindowEvent::ScaleFactorChange => WindowEvent::ScaleFactorChange,
- CWindowEvent::Resume => WindowEvent::Resume,
- CWindowEvent::RedrawRequest => WindowEvent::RedrawRequest,
- };
- Some(event)
- }
-
- pub fn wait_for_event(&self) {
- unsafe { crate::wait_for_event(self.ptr) }
- }
-
- pub fn pop_event(&self) -> bool {
- unsafe { crate::pop_event(self.ptr) }
- }
-
- pub fn wait_for_resume(&mut self) {
- unsafe { crate::wait_for_resume(self.ptr) }
- }
-
- pub fn run(&mut self, mut handler: impl FnMut(&mut Window, Option<WindowEvent>)) -> ! {
- let window_ptr = self.ptr;
-
- unsafe {
- let closure = |c_event: CWindowEvent| {
- handler(self, Self::translate_event(c_event));
- };
- let closure_data: Box<Box<dyn FnMut(CWindowEvent)>> = Box::new(Box::new(closure));
- crate::set_event_handler(window_ptr, Box::into_raw(closure_data) as *mut _);
- }
-
- loop {
- if !self.pop_event() {
- unsafe { crate::run_event_handler(window_ptr, CWindowEvent::AboutToWait) };
- }
- }
- }
-
- pub fn request_redraw(&mut self) {
- unsafe { crate::request_redraw(self.ptr) }
- }
-}
+use std::ffi::{c_void, CString};
+use std::ops::ControlFlow;
+
+use crate::{CWindowConfig, CWindowEvent};
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct WindowConfig {
+ pub title: String,
+ pub default_width: u32,
+ pub default_height: u32,
+ pub default_x: u32,
+ pub default_y: u32,
+ pub visible: bool,
+ pub borderless_fullscreen: bool,
+}
+
+pub struct Window {
+ pub(crate) ptr: *mut (),
+}
+
+pub enum WindowEvent {
+ Other = 1,
+ CloseRequest,
+ ScaleFactorChange,
+ Resume,
+ RedrawRequest,
+}
+
+impl Drop for Window {
+ fn drop(&mut self) {
+ unsafe { crate::destroy_window(self.ptr) }
+ }
+}
+
+impl Window {
+ pub fn new(config: WindowConfig) -> Self {
+ let title = CString::new(config.title.as_bytes()).unwrap();
+ let config = CWindowConfig {
+ default_width: config.default_width,
+ default_height: config.default_height,
+ default_x: config.default_x,
+ default_y: config.default_y,
+ visible: config.visible,
+ borderless_fullscreen: config.borderless_fullscreen,
+ title: title.as_ptr(),
+ };
+
+ let window = unsafe { crate::create_window(config) };
+
+ Self { ptr: window }
+ }
+
+ pub fn set_visible(&mut self, visible: bool) {
+ unsafe { crate::set_visible(self.ptr, visible) }
+ }
+
+ pub fn set_title(&mut self, title: &str) {
+ let string = CString::new(title.to_string().as_bytes()).unwrap();
+ let bytes = string.as_ptr();
+ unsafe { crate::set_title(self.ptr, bytes) }
+ }
+
+ pub fn resize(&mut self, width: u32, height: u32) {
+ unsafe { crate::resize_window(self.ptr, width, height) }
+ }
+
+ pub fn set_fullscreen(&mut self, fullscreen: bool) {
+ unsafe { crate::set_fullscreen(self.ptr, fullscreen) }
+ }
+
+ fn translate_event(event: CWindowEvent) -> Option<WindowEvent> {
+ let event = match event {
+ CWindowEvent::AboutToWait => return None,
+ CWindowEvent::Other => WindowEvent::Other,
+ CWindowEvent::CloseRequest => WindowEvent::CloseRequest,
+ CWindowEvent::ScaleFactorChange => WindowEvent::ScaleFactorChange,
+ CWindowEvent::Resume => WindowEvent::Resume,
+ CWindowEvent::RedrawRequest => WindowEvent::RedrawRequest,
+ };
+ Some(event)
+ }
+
+ pub fn wait_for_event(&self) {
+ unsafe { crate::wait_for_event(self.ptr) }
+ }
+
+ pub fn pop_event(&self) -> bool {
+ unsafe { crate::pop_event(self.ptr) }
+ }
+
+ pub fn wait_for_resume(&mut self) {
+ unsafe { crate::wait_for_resume(self.ptr) }
+ }
+
+ pub fn run(&mut self, mut handler: impl FnMut(&mut Window, Option<WindowEvent>)) -> ! {
+ let window_ptr = self.ptr;
+
+ unsafe {
+ let closure = |c_event: CWindowEvent| {
+ handler(self, Self::translate_event(c_event));
+ };
+ let closure_data: Box<Box<dyn FnMut(CWindowEvent)>> = Box::new(Box::new(closure));
+ crate::set_event_handler(window_ptr, Box::into_raw(closure_data) as *mut _);
+ }
+
+ loop {
+ if !self.pop_event() {
+ unsafe { crate::run_event_handler(window_ptr, CWindowEvent::AboutToWait) };
+ }
+ }
+ }
+
+ pub fn request_redraw(&mut self) {
+ unsafe { crate::request_redraw(self.ptr) }
+ }
+}
diff --git a/todos.txt b/todos.txt
index 8880a50..a5d94ed 100644
--- a/todos.txt
+++ b/todos.txt
@@ -1,2 +1,2 @@
-Use DirectX12 directly
-GPU accelerated vector graphics
+Use DirectX12 directly
+GPU accelerated vector graphics