Skip to content

Commit

Permalink
Write value if it's the same size.
Browse files Browse the repository at this point in the history
  • Loading branch information
adrien-zinger committed Dec 1, 2021
1 parent 14118cc commit 8ab6439
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 48 deletions.
3 changes: 1 addition & 2 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fn main() {
}
fn main() {}
8 changes: 3 additions & 5 deletions src/env.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use wasmer::{HostEnvInitError, Instance, Memory, LazyInit, WasmerEnv, Function};
use wasmer::{Function, HostEnvInitError, Instance, LazyInit, Memory, WasmerEnv};

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

impl Env {
Expand All @@ -25,9 +25,7 @@ impl WasmerEnv for Env {
if let Ok(func) = instance.exports.get_function("__new") {
self.new = Some(func.clone())
}
self.memory.initialize(
mem,
);
self.memory.initialize(mem);
Ok(())
}
}
10 changes: 5 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
mod env;
mod tools;
mod string_ptr;
mod tools;

pub use string_ptr::StringPtr;
pub use env::Env;
pub use string_ptr::StringPtr;
pub use tools::abort;

use std::fmt;
use wasmer::{Memory};
use wasmer::Memory;

pub trait Read<T> {
fn read(self, memory: &Memory) -> anyhow::Result<T>;
Expand All @@ -16,8 +16,8 @@ pub trait Read<T> {

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

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

pub type StringPtr = WasmPtr<u16, Array>;

Expand All @@ -24,27 +24,56 @@ impl Read<String> for StringPtr {

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 new = env
.new
.as_ref()
.expect("Assembly Script Runtime ot exported");
let size = i32::try_from(value.len())?;

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 offset = u32::try_from(
new.call(&[Value::I32(size << 1), Value::I32(1)])
.expect("Failed to call __new")
.get(0)
.unwrap()
.i32()
.unwrap(),
)?;
write_str(offset, value, env)?;
Ok(Box::new(StringPtr::new(offset)))
}

let from = usize::try_from(ptr)? / 2;
for (bytes, cell) in utf16.into_iter().zip(view[from..from + (size as usize)].iter()) {
cell.set(bytes);
fn write(&self, value: &str, env: &Env) -> anyhow::Result<()> {
let prev_size = size(
self.offset(),
env.memory.get_ref().expect("Failed to load memory"),
)?;
let new_size = u32::try_from(value.len())? << 1;
if prev_size == new_size {
write_str(self.offset(), value, env)?
} else {
todo!("Remove this and reallocate of bigger or smaller space")
}
Ok(Box::new(StringPtr::new(ptr as u32)))
Ok(())
}

fn write(value: &str, memory: &Env) -> anyhow::Result<Box<Self>> {
todo!()
fn free(_env: &Env) -> anyhow::Result<()> {
todo!("Release the memory from this string")
}
}

fn free() -> anyhow::Result<()> {
todo!()
fn write_str(offset: u32, value: &str, env: &Env) -> anyhow::Result<()> {
let utf16 = value.encode_utf16();
let view = env
.memory
.get_ref()
.expect("Failed to load memory")
.view::<u16>();
// We count in 32 so we have to devide by 2
let from = usize::try_from(offset)? / 2;
for (bytes, cell) in utf16.into_iter().zip(view[from..from + value.len()].iter()) {
cell.set(bytes);
}
Ok(())
}

fn size(offset: u32, memory: &Memory) -> anyhow::Result<u32> {
Expand All @@ -58,4 +87,4 @@ fn size(offset: u32, memory: &Memory) -> anyhow::Result<u32> {
} else {
anyhow::bail!("Wrong offset: can't read size")
}
}
}
12 changes: 3 additions & 9 deletions src/tools.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
use super::{Env, StringPtr, Read};
use super::{Env, Read, StringPtr};

// if get_string throws an exception abort for some reason is being called
pub fn abort(
env: &Env,
message: StringPtr,
filename: StringPtr,
line: i32,
col: i32
) {
pub fn abort(env: &Env, message: StringPtr, filename: StringPtr, line: i32, col: i32) {
let memory = env.memory.get_ref().expect("initialized memory");
let message = message.read(memory).unwrap();
let filename = filename.read(memory).unwrap();
eprintln!("Error: {} at {}:{} col: {}", message, filename, line, col);
}
}
66 changes: 55 additions & 11 deletions tests/strings.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,42 @@
use std::error::Error;
use wasmer::{Store, Module, Instance, imports, Function};
use wasmer_as::{Read, Write, StringPtr, Env, abort};
use wasmer::{imports, Function, Instance, Module, Store};
use wasmer_as::{abort, Env, Read, StringPtr, Write};

#[test]
fn read_strings() -> Result<(), Box<dyn Error>> {
let wasm_bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/test_wat.wat"));
let store = Store::default();
let module = Module::new(&store, wasm_bytes)?;
let import_object = imports! {
"env" => {
"abort" => Function::new_native_with_env(&store, Env::default(), abort),
},
};

let instance = Instance::new(&module, &import_object)?;
let memory = instance.exports.get_memory("memory").expect("get memory");

let get_string = instance
.exports
.get_native_function::<(), StringPtr>("getString")?;

let str_ptr = get_string.call()?;
let string = str_ptr.read(memory)?;

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

Ok(())
}

#[test]
fn read_alloc_strings() -> Result<(), Box<dyn Error>> {
let wasm_bytes = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/test_wat.wat"
"/tests/runtime_exported.wat"
));
let store = Store::default();
let module = Module::new(&store, wasm_bytes)?;

let import_object = imports! {
"env" => {
"abort" => Function::new_native_with_env(&store, Env::default(), abort),
Expand All @@ -19,14 +46,26 @@ fn read_strings() -> Result<(), Box<dyn Error>> {
let instance = Instance::new(&module, &import_object)?;
let memory = instance.exports.get_memory("memory").expect("get memory");

let env = Env::new(
memory.clone(),
match instance.exports.get_function("__new") {
Ok(func) => Some(func.clone()),
_ => None,
},
);

let get_string = instance
.exports
.get_native_function::<(), StringPtr>("getString")?;

let str_ptr = get_string.call()?;
let string = str_ptr.read(memory)?;

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

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

Ok(())
}
Expand All @@ -49,10 +88,13 @@ fn read_write_strings() -> Result<(), Box<dyn Error>> {
let instance = Instance::new(&module, &import_object)?;
let memory = instance.exports.get_memory("memory").expect("get memory");

let env = Env::new(memory.clone(), match instance.exports.get_function("__new") {
Ok(func) => Some(func.clone()),
_ => None
});
let env = Env::new(
memory.clone(),
match instance.exports.get_function("__new") {
Ok(func) => Some(func.clone()),
_ => None,
},
);

let get_string = instance
.exports
Expand All @@ -63,9 +105,11 @@ fn read_write_strings() -> Result<(), Box<dyn Error>> {

assert_eq!(string, "hello test");

let str_ptr_2 = StringPtr::alloc("hello return", &env)?;
str_ptr.write("hallo tast", &env)?;

let str_ptr_2 = get_string.call()?;
let string = str_ptr_2.read(memory)?;
assert_eq!(string, "hello return");

assert_eq!(string, "hallo tast");
Ok(())
}
}

0 comments on commit 8ab6439

Please sign in to comment.