1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
use crate::guest::read_bytes; use crate::prelude::*; use parking_lot::RwLock; use std::sync::Arc; use wasmer::Function; use wasmer::LazyInit; use wasmer::Memory; use wasmer::WasmerEnv; #[derive(Clone, Default, WasmerEnv)] pub struct Env { #[wasmer(export)] memory: LazyInit<Memory>, #[wasmer(export(name = "__allocate"))] allocate: LazyInit<Function>, #[wasmer(export(name = "__deallocate"))] deallocate: LazyInit<Function>, data: Arc<RwLock<Vec<u8>>>, } impl Env { pub fn set_data<I>(&self, input: I) -> Result<(), WasmError> where I: serde::Serialize + std::fmt::Debug, { *self.data.write() = holochain_serialized_bytes::encode(&input)?; Ok(()) } pub fn move_data_to_guest(&self) -> Result<GuestPtrLen, WasmError> { let guest_ptr: GuestPtr = match self .allocate_ref() .ok_or(WasmError::Memory)? .call(&[Value::I32( self.data .read() .len() .try_into() .map_err(|_| WasmError::PointerMap)?, )]) .map_err(|e| WasmError::Host(e.to_string()))?[0] { Value::I32(guest_ptr) => guest_ptr as GuestPtr, _ => return Err(WasmError::PointerMap), }; let len = self.data.read().len() as Len; crate::guest::write_bytes( self.memory_ref().ok_or(WasmError::Memory)?, guest_ptr, &self.data.read(), )?; *self.data.write() = Vec::new(); Ok(merge_u64(guest_ptr, len)) } pub fn consume_bytes_from_guest<O>(&self, guest_ptr: GuestPtr, len: Len) -> Result<O, WasmError> where O: serde::de::DeserializeOwned + std::fmt::Debug, { let bytes = read_bytes(self.memory_ref().ok_or(WasmError::Memory)?, guest_ptr, len)?; self.deallocate_ref() .ok_or(WasmError::Memory)? .call(&[ Value::I32(guest_ptr.try_into().map_err(|_| WasmError::PointerMap)?), Value::I32(len.try_into().map_err(|_| WasmError::PointerMap)?), ]) .map_err(|e| WasmError::Host(e.to_string()))?; match holochain_serialized_bytes::decode(&bytes) { Ok(v) => Ok(v), Err(e) => { tracing::error!(input_type = std::any::type_name::<O>(), bytes = ?bytes, "{}", e); Err(e.into()) } } } }