tmemory.rs - wasm-runtime - A wasm runtime
 (HTM) git clone https://git.parazyd.org/wasm-runtime
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tmemory.rs (3204B)
       ---
            1 use anyhow::Result;
            2 use wasmer::{Array, Memory, WasmPtr};
            3 
            4 use crate::error::RuntimeError;
            5 
            6 pub trait MemoryManipulation {
            7     fn write(&self, mem_offset: u32, value_slice: &[u8]) -> Result<()>;
            8     fn read(&self, mem_offset: u32, value_len: usize) -> Option<&[u8]>;
            9 }
           10 
           11 impl MemoryManipulation for Memory {
           12     fn write(&self, mem_offset: u32, value_slice: &[u8]) -> Result<()> {
           13         // Prepare WasmPtr
           14         let target_ptr: WasmPtr<u8, Array> = WasmPtr::new(mem_offset);
           15 
           16         // Allocate necessary memory space on guest
           17         let guest_value_slice = match target_ptr.deref(self, 0, value_slice.len() as u32) {
           18             Some(slice) => slice,
           19             None => [].to_vec(),
           20         };
           21 
           22         if guest_value_slice.is_empty() {
           23             return Err(RuntimeError::OutOfMemory.into())
           24         }
           25 
           26         // Copy bytes to guest
           27         for i in 0..value_slice.len() {
           28             guest_value_slice[i].set(value_slice[i]);
           29         }
           30 
           31         Ok(())
           32     }
           33 
           34     fn read(&self, mem_offset: u32, value_len: usize) -> Option<&[u8]> {
           35         let memory_size = self.size().bytes().0;
           36 
           37         if mem_offset as usize + value_len > memory_size || mem_offset as usize >= memory_size {
           38             return None
           39         }
           40 
           41         let ptr = unsafe { self.view::<u8>().as_ptr().add(mem_offset as usize) as *const u8 };
           42         unsafe { Some(std::slice::from_raw_parts(ptr, value_len)) }
           43     }
           44 }
           45 
           46 #[cfg(test)]
           47 mod tests {
           48     use super::*;
           49     use wasmer::{imports, wat2wasm, Instance, Module, Store};
           50 
           51     fn wasmer_instance() -> Instance {
           52         let wasm_bytes = wat2wasm(
           53             br#"
           54             (module
           55               (type $add_one_t (func (param i32) (result i32)))
           56               (func $add_one_f (type $add_one_t) (param $value i32) (result i32)
           57                 local.get $value
           58                 i32.const 1
           59                 i32.add)
           60               (export "add_one" (func $add_one_f))
           61               (memory $memory (export "memory") 17))
           62             "#,
           63         )
           64         .unwrap();
           65 
           66         let store = Store::default();
           67         let module = Module::new(&store, wasm_bytes).unwrap();
           68 
           69         let import_object = imports! {};
           70         Instance::new(&module, &import_object).unwrap()
           71     }
           72 
           73     #[test]
           74     fn can_write_on_memory() {
           75         let wasmer_instance = wasmer_instance();
           76 
           77         let memory = wasmer_instance.exports.get_memory("memory").unwrap();
           78         let data = String::from("data_test");
           79 
           80         let mem_addr = 0x2220;
           81 
           82         memory.write(mem_addr as u32, data.as_bytes()).unwrap();
           83 
           84         let ptr = unsafe { memory.view::<u8>().as_ptr().add(mem_addr as usize) as *const u8 };
           85         let slice_raw = unsafe { std::slice::from_raw_parts(ptr, data.len()) };
           86 
           87         assert_eq!(data.as_bytes(), slice_raw);
           88     }
           89 
           90     #[test]
           91     fn can_read_from_memory() {
           92         let wasmer_instance = wasmer_instance();
           93 
           94         let memory = wasmer_instance.exports.get_memory("memory").unwrap();
           95         let data = String::from("data_test");
           96 
           97         let mem_addr = 0x2220;
           98 
           99         memory.write(mem_addr as u32, data.as_bytes()).unwrap();
          100 
          101         let slice_raw = memory.read(mem_addr as u32, data.as_bytes().len()).unwrap();
          102 
          103         assert_eq!(data.as_bytes(), slice_raw);
          104     }
          105 }