mirror of
https://github.com/fluencelabs/interface-types
synced 2025-07-30 21:42:10 +00:00
first attempt to fix
This commit is contained in:
@@ -27,3 +27,38 @@ pub enum MemoryAccessError {
|
||||
memory_size: usize,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum MemoryWriteError {
|
||||
/// The memory doesn't exist.
|
||||
#[error("memory `{memory_index}` does not exist")]
|
||||
MemoryIsMissing {
|
||||
/// The memory index.
|
||||
memory_index: usize,
|
||||
},
|
||||
|
||||
/// The local or import function doesn't exist.
|
||||
#[error("the allocate function with index `{function_index}` doesn't exist in Wasm module")]
|
||||
AllocateFuncIsMissing {
|
||||
/// The local or import function index.
|
||||
function_index: u32,
|
||||
},
|
||||
|
||||
/// Failed to call a allocate function.
|
||||
#[error("call to allocated was failed")]
|
||||
AllocateCallFailed,
|
||||
|
||||
/// Allocate input types doesn't match with needed.
|
||||
#[error(
|
||||
"allocate func doesn't receive two i32 values,\
|
||||
probably a Wasm module's built with unsupported sdk version"
|
||||
)]
|
||||
AllocateFuncIncompatibleSignature,
|
||||
|
||||
/// Allocate output types doesn't match with needed.
|
||||
#[error(
|
||||
"allocate func doesn't return a one value of I32 type,\
|
||||
probably a Wasm module's built with unsupported sdk version"
|
||||
)]
|
||||
AllocateFuncIncompatibleOutput,
|
||||
}
|
||||
|
@@ -23,7 +23,8 @@ pub use fluence_it_types::IRecordType;
|
||||
pub use fluence_it_types::IType;
|
||||
pub use fluence_it_types::IValue;
|
||||
|
||||
pub type MResult<T> = std::result::Result<T, error::MemoryAccessError>;
|
||||
pub type ReadResult<T> = std::result::Result<T, error::MemoryAccessError>;
|
||||
pub type WriteResult<T> = std::result::Result<T, error::MemoryWriteError>;
|
||||
|
||||
/// Size of a value in a serialized view.
|
||||
pub fn ser_type_size(ty: &IType) -> usize {
|
||||
@@ -42,7 +43,7 @@ pub fn ser_type_size(ty: &IType) -> usize {
|
||||
}
|
||||
|
||||
/// Size of a value in a serialized view.
|
||||
pub fn ser_value_size(value: &IValue) -> usize {
|
||||
pub fn ser_value_size(value: &IValue) -> u32 {
|
||||
match value {
|
||||
IValue::Boolean(_) | IValue::S8(_) | IValue::U8(_) => 1,
|
||||
IValue::S16(_) | IValue::U16(_) => 2,
|
||||
|
@@ -101,7 +101,7 @@ macro_rules! read_array_ty {
|
||||
&self,
|
||||
offset: usize,
|
||||
elements_count: usize,
|
||||
) -> crate::MResult<Vec<crate::IValue>> {
|
||||
) -> crate::ReadResult<Vec<crate::IValue>> {
|
||||
let reader =
|
||||
self.sequential_reader(offset, std::mem::size_of::<$ty>() * elements_count)?;
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
|
@@ -18,7 +18,7 @@ use crate::error::MemoryAccessError;
|
||||
use crate::read_array_ty;
|
||||
use crate::read_ty;
|
||||
use crate::IValue;
|
||||
use crate::MResult;
|
||||
use crate::ReadResult;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
@@ -46,13 +46,13 @@ impl<'m> MemoryReader<'m> {
|
||||
&self,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
) -> MResult<SequentialReader<'_, '_>> {
|
||||
) -> ReadResult<SequentialReader<'_, '_>> {
|
||||
self.check_access(offset, size)?;
|
||||
|
||||
Ok(SequentialReader::new(&self, offset))
|
||||
}
|
||||
|
||||
pub fn read_raw_u8_array(&self, offset: usize, elements_count: usize) -> MResult<Vec<u8>> {
|
||||
pub fn read_raw_u8_array(&self, offset: usize, elements_count: usize) -> ReadResult<Vec<u8>> {
|
||||
let reader = self.sequential_reader(offset, elements_count)?;
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
|
||||
@@ -64,7 +64,7 @@ impl<'m> MemoryReader<'m> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn read_bool_array(&self, offset: usize, elements_count: usize) -> MResult<Vec<IValue>> {
|
||||
pub fn read_bool_array(&self, offset: usize, elements_count: usize) -> ReadResult<Vec<IValue>> {
|
||||
let reader = self.sequential_reader(offset, elements_count)?;
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
|
||||
@@ -76,7 +76,7 @@ impl<'m> MemoryReader<'m> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn check_access(&self, offset: usize, size: usize) -> MResult<()> {
|
||||
pub fn check_access(&self, offset: usize, size: usize) -> ReadResult<()> {
|
||||
let right = offset + size;
|
||||
|
||||
// the first condition is a check for overflow
|
||||
|
@@ -14,106 +14,78 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::error::MemoryAccessError;
|
||||
use crate::MResult;
|
||||
|
||||
use crate::WriteResult;
|
||||
use std::cell::Cell;
|
||||
|
||||
pub struct MemoryWriter<'m> {
|
||||
memory: &'m [Cell<u8>],
|
||||
pub type MemSlice<'m> = &'m [Cell<u8>];
|
||||
|
||||
const MEMORY_INDEX: usize = 0;
|
||||
|
||||
pub trait Heapable {
|
||||
fn allocate(&self, size: u32, type_tag: u32) -> WriteResult<usize>;
|
||||
|
||||
fn memory_slice(&self, memory_index: usize) -> WriteResult<MemSlice<'_>>;
|
||||
}
|
||||
|
||||
/// Writes values of basic types sequentially to the provided writer.
|
||||
/// It don't check memory limits for the optimization purposes,
|
||||
/// so it could be created only by the MemoryReader::sequential_reader method.
|
||||
pub struct SequentialWriter<'w, 'm> {
|
||||
writer: &'w MemoryWriter<'m>,
|
||||
pub struct MemoryWriter<'i, T: Heapable> {
|
||||
heap_manager: &'i T,
|
||||
pub(self) memory: Cell<MemSlice<'i>>,
|
||||
}
|
||||
|
||||
pub struct SequentialWriter {
|
||||
start_offset: usize,
|
||||
offset: Cell<usize>,
|
||||
}
|
||||
|
||||
impl<'m> MemoryWriter<'m> {
|
||||
pub fn new(memory: &'m [Cell<u8>]) -> Self {
|
||||
Self { memory }
|
||||
impl<'i, T: Heapable> MemoryWriter<'i, T> {
|
||||
pub fn new(heap_manager: &'i T) -> WriteResult<Self> {
|
||||
let mem_slice = heap_manager.memory_slice(MEMORY_INDEX)?;
|
||||
let memory = Cell::new(mem_slice);
|
||||
|
||||
let writer = Self {
|
||||
heap_manager,
|
||||
memory,
|
||||
};
|
||||
Ok(writer)
|
||||
}
|
||||
|
||||
pub fn write_array<const N: usize>(&self, offset: usize, values: [u8; N]) -> MResult<()> {
|
||||
self.check_access(offset, values.len())?;
|
||||
pub fn write_bytes(&self, bytes: &[u8]) -> WriteResult<usize> {
|
||||
let byte_type_tag = crate::type_tag_form_itype(&crate::IType::U8);
|
||||
let seq_writer = self.sequential_writer(bytes.len() as _, byte_type_tag)?;
|
||||
seq_writer.write_bytes(self, bytes);
|
||||
|
||||
self.memory[offset..offset + N]
|
||||
.iter()
|
||||
.zip(values.iter())
|
||||
.for_each(|(cell, &byte)| cell.set(byte));
|
||||
|
||||
Ok(())
|
||||
Ok(seq_writer.start_offset())
|
||||
}
|
||||
|
||||
// specialization of write_array for u8
|
||||
pub fn write_u8(&self, offset: usize, value: u8) -> MResult<()> {
|
||||
self.check_access(offset, 1)?;
|
||||
self.memory[offset].set(value);
|
||||
pub fn sequential_writer(&self, size: u32, type_tag: u32) -> WriteResult<SequentialWriter> {
|
||||
let offset = self.heap_manager.allocate(size, type_tag)?;
|
||||
let new_mem_slice = self.heap_manager.memory_slice(MEMORY_INDEX)?;
|
||||
self.memory.set(new_mem_slice);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// specialization of write_array for u32
|
||||
pub fn write_u32(&self, offset: usize, value: u32) -> MResult<()> {
|
||||
self.check_access(offset, 4)?;
|
||||
|
||||
let value = value.to_le_bytes();
|
||||
self.memory[offset].set(value[0]);
|
||||
self.memory[offset + 1].set(value[1]);
|
||||
self.memory[offset + 2].set(value[2]);
|
||||
self.memory[offset + 3].set(value[3]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_bytes(&self, offset: usize, bytes: &[u8]) -> MResult<()> {
|
||||
let writer = self.sequential_writer(offset, bytes.len())?;
|
||||
writer.write_bytes(bytes);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn sequential_writer(
|
||||
&self,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
) -> MResult<SequentialWriter<'_, '_>> {
|
||||
self.check_access(offset, size)?;
|
||||
|
||||
Ok(SequentialWriter::new(&self, offset))
|
||||
}
|
||||
|
||||
pub fn check_access(&self, offset: usize, size: usize) -> MResult<()> {
|
||||
let right = offset + size;
|
||||
|
||||
// the first condition is a check for overflow
|
||||
if right < offset || right >= self.memory.len() {
|
||||
return Err(MemoryAccessError::InvalidAccess {
|
||||
offset,
|
||||
size,
|
||||
memory_size: self.memory.len(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(SequentialWriter::new(offset))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 'm> SequentialWriter<'w, 'm> {
|
||||
pub(super) fn new(writer: &'w MemoryWriter<'m>, offset: usize) -> Self {
|
||||
let offset = Cell::new(offset);
|
||||
|
||||
Self { writer, offset }
|
||||
impl SequentialWriter {
|
||||
pub(self) fn new(offset: usize) -> Self {
|
||||
Self {
|
||||
offset: Cell::new(offset),
|
||||
start_offset: offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_array<const N: usize>(&self, values: [u8; N]) {
|
||||
pub fn start_offset(&self) -> usize {
|
||||
self.start_offset
|
||||
}
|
||||
|
||||
pub fn write_array<T: Heapable, const N: usize>(
|
||||
&self,
|
||||
writer: &MemoryWriter<T>,
|
||||
values: [u8; N],
|
||||
) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
log::trace!("write array: offset {} {:?}", offset, values);
|
||||
|
||||
self.writer.memory[offset..offset + N]
|
||||
writer.memory.get()[offset..offset + N]
|
||||
.iter()
|
||||
.zip(values.iter())
|
||||
.for_each(|(cell, &byte)| cell.set(byte));
|
||||
@@ -122,33 +94,35 @@ impl<'w, 'm> SequentialWriter<'w, 'm> {
|
||||
}
|
||||
|
||||
// specialization of write_array for u8
|
||||
pub fn write_u8(&self, value: u8) {
|
||||
pub fn write_u8<T: Heapable>(&self, writer: &MemoryWriter<T>, value: u8) {
|
||||
let offset = self.offset.get();
|
||||
log::trace!("write_u8: write {} to {}", value, offset);
|
||||
|
||||
self.writer.memory[offset].set(value);
|
||||
writer.memory.get()[offset].set(value);
|
||||
|
||||
self.offset.set(offset + 1);
|
||||
}
|
||||
|
||||
// specialization of write_array for u32
|
||||
pub fn write_u32(&self, value: u32) {
|
||||
pub fn write_u32<T: Heapable>(&self, writer: &MemoryWriter<T>, value: u32) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
let value = value.to_le_bytes();
|
||||
self.writer.memory[offset].set(value[0]);
|
||||
self.writer.memory[offset + 1].set(value[1]);
|
||||
self.writer.memory[offset + 2].set(value[2]);
|
||||
self.writer.memory[offset + 3].set(value[3]);
|
||||
let memory = writer.memory.get();
|
||||
|
||||
memory[offset].set(value[0]);
|
||||
memory[offset + 1].set(value[1]);
|
||||
memory[offset + 2].set(value[2]);
|
||||
memory[offset + 3].set(value[3]);
|
||||
|
||||
self.offset.set(offset + 4);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn write_bytes(&self, bytes: &[u8]) {
|
||||
pub fn write_bytes<T: Heapable>(&self, writer: &MemoryWriter<T>, bytes: &[u8]) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
self.writer.memory[offset..offset + bytes.len()]
|
||||
let memory = writer.memory.get();
|
||||
memory[offset..offset + bytes.len()]
|
||||
.iter()
|
||||
.zip(bytes)
|
||||
.for_each(|(cell, &byte)| cell.set(byte));
|
||||
|
Reference in New Issue
Block a user