-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
- Loading branch information
1 parent
6fd283b
commit 8adce67
Showing
11 changed files
with
261 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,135 @@ | ||
use core::cell::RefCell; | ||
use core::{ | ||
cell::{Ref, RefCell}, | ||
ffi::CStr, | ||
}; | ||
|
||
use crate::{GlobalInstance, MemoryInstance, Result}; | ||
use alloc::{ | ||
ffi::CString, | ||
rc::Rc, | ||
string::{String, ToString}, | ||
vec::Vec, | ||
}; | ||
use tinywasm_types::WasmValue; | ||
|
||
use crate::{GlobalInstance, MemoryInstance}; | ||
use alloc::rc::Rc; | ||
// This module essentially contains the public APIs to interact with the data stored in the store | ||
|
||
/// A reference to a memory instance | ||
#[derive(Debug, Clone)] | ||
pub struct MemoryRef { | ||
pub(crate) _instance: Rc<RefCell<MemoryInstance>>, | ||
pub(crate) instance: Rc<RefCell<MemoryInstance>>, | ||
} | ||
|
||
/// A borrowed reference to a memory instance | ||
#[derive(Debug)] | ||
pub struct BorrowedMemory<'a> { | ||
pub(crate) instance: Ref<'a, MemoryInstance>, | ||
} | ||
|
||
impl<'a> BorrowedMemory<'a> { | ||
/// Load a slice of memory | ||
pub fn load(&self, offset: usize, len: usize) -> Result<&[u8]> { | ||
self.instance.load(offset, 0, len) | ||
} | ||
|
||
/// Load a C-style string from memory | ||
pub fn load_cstr(&self, offset: usize, len: usize) -> Result<&CStr> { | ||
let bytes = self.load(offset, len)?; | ||
CStr::from_bytes_with_nul(bytes).map_err(|_| crate::Error::Other("Invalid C-style string".to_string())) | ||
} | ||
|
||
/// Load a C-style string from memory, stopping at the first nul byte | ||
pub fn load_cstr_until_nul(&self, offset: usize, max_len: usize) -> Result<&CStr> { | ||
let bytes = self.load(offset, max_len)?; | ||
CStr::from_bytes_until_nul(bytes).map_err(|_| crate::Error::Other("Invalid C-style string".to_string())) | ||
} | ||
} | ||
|
||
impl MemoryRef { | ||
/// Borrow the memory instance | ||
/// | ||
/// This is useful for when you want to load only a reference to a slice of memory | ||
/// without copying the data. The borrow should be dropped before any other memory | ||
/// operations are performed. | ||
pub fn borrow(&self) -> BorrowedMemory<'_> { | ||
BorrowedMemory { instance: self.instance.borrow() } | ||
} | ||
|
||
/// Load a slice of memory | ||
pub fn load_vec(&self, offset: usize, len: usize) -> Result<Vec<u8>> { | ||
self.instance.borrow().load(offset, 0, len).map(|x| x.to_vec()) | ||
} | ||
|
||
/// Grow the memory by the given number of pages | ||
pub fn grow(&self, delta_pages: i32) -> Option<i32> { | ||
self.instance.borrow_mut().grow(delta_pages) | ||
} | ||
|
||
/// Get the current size of the memory in pages | ||
pub fn page_count(&self) -> usize { | ||
self.instance.borrow().page_count() | ||
} | ||
|
||
/// Copy a slice of memory to another place in memory | ||
pub fn copy_within(&self, src: usize, dst: usize, len: usize) -> Result<()> { | ||
self.instance.borrow_mut().copy_within(src, dst, len) | ||
} | ||
|
||
/// Fill a slice of memory with a value | ||
pub fn fill(&self, offset: usize, len: usize, val: u8) -> Result<()> { | ||
self.instance.borrow_mut().fill(offset, len, val) | ||
} | ||
|
||
/// Load a UTF-8 string from memory | ||
pub fn load_string(&self, offset: usize, len: usize) -> Result<String> { | ||
let bytes = self.load_vec(offset, len)?; | ||
Ok(String::from_utf8(bytes).map_err(|_| crate::Error::Other("Invalid UTF-8 string".to_string()))?) | ||
} | ||
|
||
/// Load a C-style string from memory | ||
pub fn load_cstring(&self, offset: usize, len: usize) -> Result<CString> { | ||
Ok(CString::from(self.borrow().load_cstr(offset, len)?)) | ||
} | ||
|
||
/// Load a C-style string from memory, stopping at the first nul byte | ||
pub fn load_cstring_until_nul(&self, offset: usize, max_len: usize) -> Result<CString> { | ||
Ok(CString::from(self.borrow().load_cstr_until_nul(offset, max_len)?)) | ||
} | ||
|
||
/// Load a JavaScript-style utf-16 string from memory | ||
pub fn load_js_string(&self, offset: usize, len: usize) -> Result<String> { | ||
let memref = self.borrow(); | ||
let bytes = memref.load(offset, len)?; | ||
let mut string = String::new(); | ||
for i in 0..(len / 2) { | ||
let c = u16::from_le_bytes([bytes[i * 2], bytes[i * 2 + 1]]); | ||
string.push( | ||
char::from_u32(c as u32).ok_or_else(|| crate::Error::Other("Invalid UTF-16 string".to_string()))?, | ||
); | ||
} | ||
Ok(string) | ||
} | ||
|
||
/// Store a slice of memory | ||
pub fn store(&self, offset: usize, len: usize, data: &[u8]) -> Result<()> { | ||
self.instance.borrow_mut().store(offset, 0, data, len) | ||
} | ||
} | ||
|
||
/// A reference to a global instance | ||
#[derive(Debug, Clone)] | ||
pub struct GlobalRef { | ||
pub(crate) _instance: Rc<RefCell<GlobalInstance>>, | ||
pub(crate) instance: Rc<RefCell<GlobalInstance>>, | ||
} | ||
|
||
impl GlobalRef { | ||
/// Get the value of the global | ||
pub fn get(&self) -> WasmValue { | ||
self.instance.borrow().get() | ||
} | ||
|
||
/// Set the value of the global | ||
pub fn set(&self, val: WasmValue) -> Result<()> { | ||
self.instance.borrow_mut().set(val) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,28 @@ | ||
#![no_std] | ||
#![no_main] | ||
|
||
#[cfg(not(test))] | ||
#[panic_handler] | ||
fn panic(_info: &core::panic::PanicInfo) -> ! { | ||
core::arch::wasm32::unreachable() | ||
} | ||
|
||
#[link(wasm_import_module = "env")] | ||
extern "C" { | ||
fn printi32(x: i32); | ||
fn print_utf8(location: i32, len: i32); | ||
} | ||
|
||
const ARG: &[u8] = &[0u8; 100]; | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn arg_ptr() -> i32 { | ||
ARG.as_ptr() as i32 | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn add_and_print(lh: i32, rh: i32) { | ||
printi32(lh + rh); | ||
pub unsafe extern "C" fn arg_size() -> i32 { | ||
ARG.len() as i32 | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn hello(len: i32) { | ||
let arg = core::str::from_utf8(&ARG[0..len as usize]).unwrap(); | ||
let res = format!("Hello, {}!", arg).as_bytes().to_vec(); | ||
|
||
let len = res.len() as i32; | ||
let ptr = res.leak().as_ptr() as i32; | ||
print_utf8(ptr, len); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#![no_std] | ||
#![no_main] | ||
|
||
#[cfg(not(test))] | ||
#[panic_handler] | ||
fn panic(_info: &core::panic::PanicInfo) -> ! { | ||
core::arch::wasm32::unreachable() | ||
} | ||
|
||
#[link(wasm_import_module = "env")] | ||
extern "C" { | ||
fn printi32(x: i32); | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn add_and_print(lh: i32, rh: i32) { | ||
printi32(lh + rh); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.