simplify the interface and make the functions more explicit

This commit is contained in:
Christof Petig 2023-06-24 15:52:40 +02:00
parent 01223d7174
commit c9ff9e9841
3 changed files with 32 additions and 99 deletions

View File

@ -110,7 +110,7 @@ impl EcsAccessManager {
/// buffer calling the `wasm_prepare_buffer` function Note: There is
/// probably optimizations that can be done using less restrictive
/// ordering
pub fn get_pointer(
fn get_pointer(
store: &mut StoreMut,
object_length: <MemoryModel as wasmer::MemorySize>::Offset,
allocator: &TypedFunction<
@ -123,45 +123,17 @@ pub fn get_pointer(
.map_err(MemoryAllocationError::CantAllocate)
}
/// This function writes an object to WASM memory returning a pointer and a
/// length. Will realloc the buffer is not wide enough
pub fn write_data<T: Serialize>(
store: &mut StoreMut,
memory: &Memory,
allocator: &TypedFunction<
<MemoryModel as wasmer::MemorySize>::Offset,
WasmPtr<u8, MemoryModel>,
>,
object: &T,
) -> Result<
(
WasmPtr<u8, MemoryModel>,
<MemoryModel as wasmer::MemorySize>::Offset,
),
PluginModuleError,
> {
write_bytes(
store,
memory,
allocator,
(
&bincode::serialize(object).map_err(PluginModuleError::Encoding)?,
&[],
),
)
}
/// This functions wraps the serialization process
pub fn serialize_data<T: Serialize>(object: &T) -> Result<Vec<u8>, PluginModuleError> {
fn serialize_data<T: Serialize>(object: &T) -> Result<Vec<u8>, PluginModuleError> {
bincode::serialize(object).map_err(PluginModuleError::Encoding)
}
/// This function writes an object to the wasm memory using the allocator if
/// necessary using length padding.
///
/// With length padding the first 8 bytes written are the length of the the
/// With length padding the first bytes written are the length of the the
/// following slice (The object serialized).
pub fn write_data_as_pointer<T: Serialize>(
pub(crate) fn write_serialized_with_length<T: Serialize>(
store: &mut StoreMut,
memory: &Memory,
allocator: &TypedFunction<
@ -170,7 +142,7 @@ pub fn write_data_as_pointer<T: Serialize>(
>,
object: &T,
) -> Result<WasmPtr<u8, MemoryModel>, PluginModuleError> {
write_bytes_as_pointer(store, memory, allocator, &serialize_data(object)?)
write_length_and_bytes(store, memory, allocator, &serialize_data(object)?)
}
/// This function writes an raw bytes to WASM memory returning a pointer and
@ -179,7 +151,7 @@ pub fn write_data_as_pointer<T: Serialize>(
/// As this function is often called after prepending a length to an existing
/// object it accepts two slices and concatenates them to cut down copying in
/// the caller.
pub fn write_bytes(
pub(crate) fn write_bytes(
store: &mut StoreMut,
memory: &Memory,
allocator: &TypedFunction<
@ -211,9 +183,9 @@ pub fn write_bytes(
/// This function writes bytes to the wasm memory using the allocator if
/// necessary using length padding.
///
/// With length padding the first 8 bytes written are the length of the the
/// With length padding the first bytes written are the length of the the
/// following slice.
pub fn write_bytes_as_pointer(
pub(crate) fn write_length_and_bytes(
store: &mut StoreMut,
memory: &Memory,
allocator: &TypedFunction<
@ -228,7 +200,7 @@ pub fn write_bytes_as_pointer(
/// This function reads data from memory at a position with the array length and
/// converts it to an object using bincode
pub fn read_data<'a, T: for<'b> Deserialize<'b>>(
pub(crate) fn read_serialized<'a, T: for<'b> Deserialize<'b>>(
memory: &'a Memory,
store: &StoreRef,
ptr: WasmPtr<u8, MemoryModel>,
@ -241,7 +213,7 @@ pub fn read_data<'a, T: for<'b> Deserialize<'b>>(
/// This function reads raw bytes from memory at a position with the array
/// length
pub fn read_bytes(
pub(crate) fn read_bytes(
memory: &Memory,
store: &StoreRef,
ptr: WasmPtr<u8, MemoryModel>,
@ -253,7 +225,7 @@ pub fn read_bytes(
}
/// This function reads a constant amount of raw bytes from memory
pub fn read_exact_bytes<const N: usize>(
pub(crate) fn read_exact_bytes<const N: usize>(
memory: &Memory,
store: &StoreRef,
ptr: WasmPtr<u8, MemoryModel>,

View File

@ -1,5 +1,5 @@
use hashbrown::HashSet;
use std::{convert::TryInto, marker::PhantomData, sync::Arc};
use std::{marker::PhantomData, sync::Arc};
use wasmer::{
imports, AsStoreMut, AsStoreRef, Function, FunctionEnv, FunctionEnvMut, Instance, Memory,
@ -47,13 +47,15 @@ impl PluginModule {
ptr: WasmPtr<u8, MemoryModel>,
len: <MemoryModel as wasmer::MemorySize>::Offset,
) {
handle_actions(match env.data().read_data(&env.as_store_ref(), ptr, len) {
Ok(e) => e,
Err(e) => {
tracing::error!(?e, "Can't decode action");
return;
handle_actions(
match env.data().read_serialized(&env.as_store_ref(), ptr, len) {
Ok(e) => e,
Err(e) => {
tracing::error!(?e, "Can't decode action");
return;
},
},
});
);
}
fn raw_retrieve_action(
@ -62,16 +64,16 @@ impl PluginModule {
ptr: WasmPtr<u8, MemoryModel>,
len: <MemoryModel as wasmer::MemorySize>::Offset,
) -> <MemoryModel as wasmer::MemorySize>::Offset {
let out = match env.data().read_data(&env.as_store_ref(), ptr, len) {
let out = match env.data().read_serialized(&env.as_store_ref(), ptr, len) {
Ok(data) => retrieve_action(&env.data().ecs, data),
Err(e) => Err(RetrieveError::BincodeError(e.to_string())),
};
let data = env.data().clone();
// If an error happen set the i64 to 0 so the WASM side can tell an error
// occured
data.write_data_as_pointer(&mut env.as_store_mut(), &out)
.unwrap_or_else(|_e| WasmPtr::null())
data.write_serialized_with_length(&mut env.as_store_mut(), &out)
.unwrap_or_else(|_e|
// return a null pointer so the WASM side can tell an error occured
WasmPtr::null())
.offset()
}
@ -183,28 +185,6 @@ impl<T: Event> PreparedEventQuery<T> {
pub fn get_function_name(&self) -> &str { &self.function_name }
}
/// This function split a u128 in two u64 encoding them as le bytes
pub fn from_u128(i: u128) -> (u64, u64) {
let i = i.to_le_bytes();
(
u64::from_le_bytes(i[0..8].try_into().unwrap()),
u64::from_le_bytes(i[8..16].try_into().unwrap()),
)
}
/// This function merge two u64 encoded as le in one u128
pub fn to_u128(a: u64, b: u64) -> u128 {
let a = a.to_le_bytes();
let b = b.to_le_bytes();
u128::from_le_bytes([a, b].concat().try_into().unwrap())
}
/// This function encode a u64 into a i64 using le bytes
pub fn to_i64(i: u64) -> i64 { i64::from_le_bytes(i.to_le_bytes()) }
/// This function decode a i64 into a u64 using le bytes
pub fn from_i64(i: i64) -> u64 { u64::from_le_bytes(i.to_le_bytes()) }
// This function is not public because this function should not be used without
// an interface to limit unsafe behaviours
fn execute_raw(

View File

@ -65,41 +65,25 @@ impl HostFunctionEnvironment {
#[inline]
pub fn name(&self) -> &str { &self.name }
/// This function is a safe interface to WASM memory that writes data to the
/// memory returning a pointer and length
pub fn write_data<T: Serialize>(
&self,
store: &mut StoreMut,
object: &T,
) -> Result<
(
WasmPtr<u8, MemoryModel>,
<MemoryModel as wasmer::MemorySize>::Offset,
),
PluginModuleError,
> {
memory_manager::write_data(store, self.memory(), self.allocator(), object)
}
/// This function is a safe interface to WASM memory that writes data to the
/// memory returning a pointer and length
pub fn write_data_as_pointer<T: Serialize>(
/// This function is a safe interface to WASM memory that serializes and
/// writes an object to linear memory returning a pointer
pub fn write_serialized_with_length<T: Serialize>(
&self,
store: &mut StoreMut,
object: &T,
) -> Result<WasmPtr<u8, MemoryModel>, PluginModuleError> {
memory_manager::write_data_as_pointer(store, self.memory(), self.allocator(), object)
memory_manager::write_serialized_with_length(store, self.memory(), self.allocator(), object)
}
/// This function is a safe interface to WASM memory that reads memory from
/// pointer and length returning an object
pub fn read_data<T: DeserializeOwned>(
pub fn read_serialized<T: DeserializeOwned>(
&self,
store: &StoreRef,
position: WasmPtr<u8, MemoryModel>,
length: <MemoryModel as wasmer::MemorySize>::Offset,
) -> Result<T, bincode::Error> {
memory_manager::read_data(self.memory(), store, position, length)
memory_manager::read_serialized(self.memory(), store, position, length)
}
/// This function is a safe interface to WASM memory that reads memory from
@ -110,10 +94,7 @@ impl HostFunctionEnvironment {
ptr: WasmPtr<u8, MemoryModel>,
len: <MemoryModel as wasmer::MemorySize>::Offset,
) -> Result<Vec<u8>, PluginModuleError> {
self.memory.as_ref().map_or_else(
|| Err(PluginModuleError::InvalidPointer),
|m| memory_manager::read_bytes(m, store, ptr, len),
)
memory_manager::read_bytes(self.memory(), store, ptr, len)
}
pub fn args_from_instance(