Skip to content

Commit

Permalink
Add an allocation of string
Browse files Browse the repository at this point in the history
Write in memory if the assembly script is build with
`npm run asbuild:untouched -- --exportRuntime`
  • Loading branch information
adrien-zinger committed Dec 1, 2021
1 parent 542e708 commit 660a750
Show file tree
Hide file tree
Showing 8 changed files with 2,635 additions and 25 deletions.
8 changes: 1 addition & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,4 @@ build = "build.rs"

[dependencies]
wasmer = "2.0"

[build-dependencies]
skeptic = "0.13"

[dev-dependencies]
skeptic = "0.13"
wasmer = "2.0"
anyhow = "1"
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ Helpers for dealing with assemblyscript memory inside wasmer-runtime

```rust
use std::error::Error;
use wasmer::{Instance, Memory, MemoryType, Module, Store};
use wasmer_as::{AsmScriptRead, AsmScriptStringPtr, Env, abort};
use wasmer::{Store, Module, Instance, imports, Function};
use wasmer_as::{Read, Write, StringPtr, Env, abort};

fn main() -> Result<(), Box<dyn Error>> {
let wasm_bytes = include_bytes!(concat!(
Expand All @@ -31,13 +31,17 @@ fn main() -> Result<(), Box<dyn Error>> {
let results = get_string.call(&[])?;

let str_ptr = results.first().expect("get pointer");
let str_ptr = AsmScriptStringPtr::new(str_ptr.unwrap_i32() as u32);
let str_ptr = StringPtr::new(str_ptr.unwrap_i32() as u32);

let memory = instance.exports.get_memory("memory").expect("get memory");
let string = str_ptr.read(memory)?;

assert_eq!(string, "$¢ह한𝌆");

let str_ptr_2 = StringPtr::alloc("hello return", &env)?;
let string = str_ptr_2.read(memory)?;
assert_eq!(string, "hello return");

Ok(())
}
```
3 changes: 0 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
extern crate skeptic;

fn main() {
skeptic::generate_doc_tests(&["README.md"]);
}
26 changes: 20 additions & 6 deletions src/env.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
use wasmer::{HostEnvInitError, Instance, LazyInit, Memory, WasmerEnv};
use wasmer::{HostEnvInitError, Instance, Memory, LazyInit, WasmerEnv, Function};

#[derive(Clone, Default)]
pub struct Env {
pub memory: LazyInit<Memory>,
pub new: Option<Function>
}

impl Env {
pub fn new(memory: Memory, new: Option<Function>) -> Env {
let mut env = Env::default();
env.memory.initialize(memory);
env.new = new;
env
}
}

impl WasmerEnv for Env {
fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> {
let mem = instance
.exports
.get_memory("memory")
.map_err(HostEnvInitError::from)?
.clone();
if let Ok(func) = instance.exports.get_function("__new") {
self.new = Some(func.clone())
}
self.memory.initialize(
instance
.exports
.get_memory("memory")
.map_err(HostEnvInitError::from)?
.clone(),
mem,
);
Ok(())
}
Expand Down
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use wasmer::{Memory};
pub trait Read<T> {
fn read(self, memory: &Memory) -> Result<T, Error>;
fn size(self, memory: &Memory) -> Result<u32, Error>;
fn malloc(value: &str, memory: &Memory) -> Result<Box<Self>, Error>;
}

pub trait Write<T> {
fn alloc(value: &str, memory: &Env) -> anyhow::Result<Box<Self>>;
}

#[derive(Debug)]
Expand Down
22 changes: 18 additions & 4 deletions src/string_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use wasmer::{WasmPtr, Array};
use super::{Read, Memory, Error};
use std::convert::TryFrom;
use wasmer::{WasmPtr, Array, Value};
use super::{Read, Memory, Error, Env, Write};

pub type StringPtr = WasmPtr<u16, Array>;

Expand Down Expand Up @@ -28,8 +29,21 @@ impl Read<String> for StringPtr {
Err(Error::Mem("Wrong offset: can't read size"))
}
}
}

fn malloc(_value: &str, _memory: &Memory) -> Result<Box<StringPtr>, Error> {
todo!();
impl Write<String> for StringPtr {
fn alloc(value: &str, env: &Env) -> anyhow::Result<Box<StringPtr>> {
let new = env.new.as_ref().expect("Assembly Script Runtime ot exported");
let size = i32::try_from(value.len()).expect("Cannot convert value size t i32");

let ptr = new.call(&[Value::I32(size << 1), Value::I32(1)]).expect("Failed to call __new").get(0).unwrap().i32().unwrap();
let utf16 = value.encode_utf16();
let view = env.memory.get_ref().expect("Failed to load memory").view::<u16>();

let from = usize::try_from(ptr)?;
for (bytes, cell) in utf16.into_iter().zip(view[from / 2..(from / 2 + ((size) as usize))].iter()) {
cell.set(bytes);
}
Ok(Box::new(StringPtr::new(ptr as u32)))
}
}
Loading

0 comments on commit 660a750

Please sign in to comment.