mirror of
https://github.com/fluencelabs/interface-types
synced 2025-06-16 16:31:26 +00:00
Refactor memory access interface to fix that writer does not update memory after allocation (#17)
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "it-lilo"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
authors = ["Fluence Labs"]
|
||||
description = "Defines some helper utils for lifting/lowering IT"
|
||||
edition = "2018"
|
||||
@ -12,7 +12,7 @@ path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence-it-types = { path = "../it-types/", version = "0.3.0" }
|
||||
it-memory-traits = { path = "../it-memory-traits", version = "0.2.0" }
|
||||
it-memory-traits = { path = "../it-memory-traits", version = "0.3.0" }
|
||||
|
||||
paste = "1.0.5"
|
||||
thiserror = "1.0.24"
|
||||
|
@ -22,9 +22,9 @@ use crate::utils::ser_type_size;
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
|
||||
use it_memory_traits::{SequentialMemoryView, SequentialReader};
|
||||
use it_memory_traits::MemoryView;
|
||||
|
||||
pub fn array_lift_memory<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
pub fn array_lift_memory<R: RecordResolvable, MV: MemoryView>(
|
||||
lifter: &ILifter<'_, R, MV>,
|
||||
value_type: &IType,
|
||||
offset: u32,
|
||||
@ -61,7 +61,7 @@ pub fn array_lift_memory<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'
|
||||
Ok(IValue::Array(ivalues))
|
||||
}
|
||||
|
||||
fn read_string_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
fn read_string_array<R: RecordResolvable, MV: MemoryView>(
|
||||
lifter: &ILifter<'_, R, MV>,
|
||||
offset: u32,
|
||||
elements_count: u32,
|
||||
@ -83,7 +83,7 @@ fn read_string_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn read_array_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
fn read_array_array<R: RecordResolvable, MV: MemoryView>(
|
||||
lifter: &ILifter<'_, R, MV>,
|
||||
ty: &IType,
|
||||
offset: u32,
|
||||
@ -105,7 +105,7 @@ fn read_array_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn read_record_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
fn read_record_array<R: RecordResolvable, MV: MemoryView>(
|
||||
lifter: &ILifter<'_, R, MV>,
|
||||
record_type_id: u64,
|
||||
offset: u32,
|
||||
|
@ -18,6 +18,7 @@ use super::ILifter;
|
||||
use super::LiError;
|
||||
use super::LiResult;
|
||||
use super::MemoryReader;
|
||||
use crate::lifter::memory_reader::SequentialReader;
|
||||
use crate::traits::RecordResolvable;
|
||||
use crate::utils::record_size;
|
||||
use crate::IRecordType;
|
||||
@ -25,9 +26,9 @@ use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::NEVec;
|
||||
|
||||
use it_memory_traits::{SequentialMemoryView, SequentialReader};
|
||||
use it_memory_traits::MemoryView;
|
||||
|
||||
pub fn record_lift_memory<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
pub fn record_lift_memory<R: RecordResolvable, MV: MemoryView>(
|
||||
lifter: &ILifter<'_, R, MV>,
|
||||
record_type: &IRecordType,
|
||||
offset: u32,
|
||||
@ -68,9 +69,9 @@ pub fn record_lift_memory<R: RecordResolvable, MV: for<'a> SequentialMemoryView<
|
||||
Ok(IValue::Record(record))
|
||||
}
|
||||
|
||||
fn read_string<MV: for<'a> SequentialMemoryView<'a>>(
|
||||
fn read_string<MV: MemoryView>(
|
||||
reader: &MemoryReader<MV>,
|
||||
seq_reader: &<MV as SequentialMemoryView<'_>>::SR,
|
||||
seq_reader: &SequentialReader<'_, MV>,
|
||||
) -> LiResult<String> {
|
||||
let offset = seq_reader.read_u32();
|
||||
let size = seq_reader.read_u32();
|
||||
@ -81,9 +82,9 @@ fn read_string<MV: for<'a> SequentialMemoryView<'a>>(
|
||||
Ok(string)
|
||||
}
|
||||
|
||||
fn read_byte_array<MV: for<'a> SequentialMemoryView<'a>>(
|
||||
fn read_byte_array<MV: MemoryView>(
|
||||
reader: &MemoryReader<MV>,
|
||||
seq_reader: &<MV as SequentialMemoryView<'_>>::SR,
|
||||
seq_reader: &SequentialReader<'_, MV>,
|
||||
) -> LiResult<IValue> {
|
||||
let offset = seq_reader.read_u32();
|
||||
let size = seq_reader.read_u32();
|
||||
@ -93,9 +94,9 @@ fn read_byte_array<MV: for<'a> SequentialMemoryView<'a>>(
|
||||
Ok(IValue::ByteArray(array))
|
||||
}
|
||||
|
||||
fn read_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
fn read_array<R: RecordResolvable, MV: MemoryView>(
|
||||
lifter: &ILifter<'_, R, MV>,
|
||||
seq_reader: &<MV as SequentialMemoryView<'_>>::SR,
|
||||
seq_reader: &SequentialReader<'_, MV>,
|
||||
value_type: &IType,
|
||||
) -> LiResult<IValue> {
|
||||
let offset = seq_reader.read_u32();
|
||||
@ -104,9 +105,9 @@ fn read_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
super::array_lift_memory(lifter, value_type, offset, size)
|
||||
}
|
||||
|
||||
fn read_record<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
fn read_record<R: RecordResolvable, MV: MemoryView>(
|
||||
lifter: &ILifter<'_, R, MV>,
|
||||
seq_reader: &<MV as SequentialMemoryView<'_>>::SR,
|
||||
seq_reader: &SequentialReader<'_, MV>,
|
||||
record_type_id: u64,
|
||||
) -> LiResult<IValue> {
|
||||
let offset = seq_reader.read_u32();
|
||||
|
@ -17,34 +17,34 @@
|
||||
#[macro_export]
|
||||
macro_rules! value_der {
|
||||
($self:expr, $offset:expr, @seq_start $($ids:tt),* @seq_end) => {
|
||||
[$($self.memory.get($offset + $ids)),+]
|
||||
[$($self.reader.view.read_byte($offset + $ids)),+]
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 1) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0 @seq_end);
|
||||
crate::value_der!($self, $offset, @seq_start 0 @seq_end)
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 2) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1 @seq_end);
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1 @seq_end)
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 4) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3 @seq_end);
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3 @seq_end)
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 8) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7 @seq_end);
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7 @seq_end)
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 16) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 @seq_end);
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 @seq_end)
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! read_ty {
|
||||
($func_name:ident, $ty:ty, 1) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
pub fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 1));
|
||||
|
||||
@ -54,7 +54,7 @@ macro_rules! read_ty {
|
||||
};
|
||||
|
||||
($func_name:ident, $ty:ty, 2) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
pub fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 2));
|
||||
|
||||
@ -64,7 +64,7 @@ macro_rules! read_ty {
|
||||
};
|
||||
|
||||
($func_name:ident, $ty:ty, 4) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
pub fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 4));
|
||||
|
||||
@ -74,7 +74,7 @@ macro_rules! read_ty {
|
||||
};
|
||||
|
||||
($func_name:ident, $ty:ty, 8) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
pub fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 8));
|
||||
|
||||
@ -84,7 +84,7 @@ macro_rules! read_ty {
|
||||
};
|
||||
|
||||
($func_name:ident, $ty:ty, 16) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
pub fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 16));
|
||||
|
||||
|
@ -16,15 +16,18 @@
|
||||
|
||||
use super::LiResult;
|
||||
use crate::read_array_ty;
|
||||
use crate::read_ty;
|
||||
use crate::IValue;
|
||||
|
||||
use it_memory_traits::{SequentialMemoryView, SequentialReader};
|
||||
use it_memory_traits::MemoryView;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
pub struct MemoryReader<MV> {
|
||||
pub(self) view: MV,
|
||||
}
|
||||
|
||||
impl<MV: for<'a> SequentialMemoryView<'a>> MemoryReader<MV> {
|
||||
impl<MV: MemoryView> MemoryReader<MV> {
|
||||
pub fn new(view: MV) -> Self {
|
||||
Self { view }
|
||||
}
|
||||
@ -32,12 +35,9 @@ impl<MV: for<'a> SequentialMemoryView<'a>> MemoryReader<MV> {
|
||||
/// Returns reader that allows read sequentially. It's important that memory limit is checked
|
||||
/// only inside this function. All others functions of the returned reader don't have any
|
||||
/// checks assuming that reader is well-formed.
|
||||
pub fn sequential_reader(
|
||||
&self,
|
||||
offset: u32,
|
||||
size: u32,
|
||||
) -> LiResult<<MV as SequentialMemoryView<'_>>::SR> {
|
||||
let seq_reader = self.view.sequential_reader(offset, size)?;
|
||||
pub fn sequential_reader(&self, offset: u32, size: u32) -> LiResult<SequentialReader<'_, MV>> {
|
||||
self.view.check_bounds(offset, size)?;
|
||||
let seq_reader = SequentialReader::new(&self, offset);
|
||||
Ok(seq_reader)
|
||||
}
|
||||
|
||||
@ -78,3 +78,32 @@ impl<MV: for<'a> SequentialMemoryView<'a>> MemoryReader<MV> {
|
||||
read_array_ty!(read_i64_array, i64, I64);
|
||||
read_array_ty!(read_f64_array, f64, F64);
|
||||
}
|
||||
|
||||
pub struct SequentialReader<'r, MV: MemoryView> {
|
||||
reader: &'r MemoryReader<MV>,
|
||||
offset: Cell<u32>,
|
||||
}
|
||||
|
||||
impl<'r, MV: MemoryView> SequentialReader<'r, MV> {
|
||||
fn new(reader: &'r MemoryReader<MV>, offset: u32) -> Self {
|
||||
Self {
|
||||
reader,
|
||||
offset: Cell::new(offset),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_bool(&self) -> bool {
|
||||
self.read_u8() != 0
|
||||
}
|
||||
|
||||
read_ty!(read_u8, u8, 1);
|
||||
read_ty!(read_i8, i8, 1);
|
||||
read_ty!(read_u16, u16, 2);
|
||||
read_ty!(read_i16, i16, 2);
|
||||
read_ty!(read_u32, u32, 4);
|
||||
read_ty!(read_i32, i32, 4);
|
||||
read_ty!(read_f32, f32, 4);
|
||||
read_ty!(read_u64, u64, 8);
|
||||
read_ty!(read_i64, i64, 8);
|
||||
read_ty!(read_f64, f64, 8);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ pub use memory_reader::MemoryReader;
|
||||
|
||||
use super::traits::RecordResolvable;
|
||||
|
||||
pub use it_memory_traits::SequentialMemoryView;
|
||||
pub use it_memory_traits::MemoryView;
|
||||
|
||||
pub type LiResult<T> = std::result::Result<T, error::LiError>;
|
||||
|
||||
@ -36,7 +36,7 @@ pub struct ILifter<'r, R: RecordResolvable, MV> {
|
||||
pub resolver: &'r R,
|
||||
}
|
||||
|
||||
impl<'r, R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>> ILifter<'r, R, MV> {
|
||||
impl<'r, R: RecordResolvable, MV: MemoryView> ILifter<'r, R, MV> {
|
||||
pub fn new(view: MV, resolver: &'r R) -> Self {
|
||||
let reader = MemoryReader::new(view);
|
||||
Self { reader, resolver }
|
||||
|
@ -21,7 +21,7 @@ use crate::utils::ser_value_size;
|
||||
use crate::utils::type_tag_form_ivalue;
|
||||
use crate::IValue;
|
||||
|
||||
use it_memory_traits::{SequentialMemoryView, SequentialWriter};
|
||||
use it_memory_traits::MemoryView;
|
||||
|
||||
pub struct LoweredArray {
|
||||
pub offset: u32,
|
||||
@ -38,7 +38,7 @@ impl LoweredArray {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn array_lower_memory<A: Allocatable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
pub fn array_lower_memory<A: Allocatable<MV>, MV: MemoryView>(
|
||||
lowerer: &ILowerer<'_, A, MV>,
|
||||
array_values: Vec<IValue>,
|
||||
) -> LoResult<LoweredArray> {
|
||||
@ -54,40 +54,40 @@ pub fn array_lower_memory<A: Allocatable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
// here it's known that all interface values have the same type
|
||||
for value in array_values {
|
||||
match value {
|
||||
IValue::Boolean(value) => seq_writer.write_u8(value as _),
|
||||
IValue::S8(value) => seq_writer.write_u8(value as _),
|
||||
IValue::S16(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::S32(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::S64(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::U8(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::U16(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::U32(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::U64(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::I32(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::I64(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::F32(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::F64(value) => seq_writer.write_bytes(&value.to_le_bytes()),
|
||||
IValue::Boolean(value) => seq_writer.write_u8(&lowerer.writer, value as _),
|
||||
IValue::S8(value) => seq_writer.write_u8(&lowerer.writer, value as _),
|
||||
IValue::S16(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::S32(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::S64(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::U8(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::U16(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::U32(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::U64(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::I32(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::I64(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::F32(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::F64(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()),
|
||||
IValue::String(value) => {
|
||||
let offset = lowerer.writer.write_bytes(&value.as_bytes())? as u32;
|
||||
|
||||
seq_writer.write_bytes(&offset.to_le_bytes());
|
||||
seq_writer.write_bytes(&(value.len() as u32).to_le_bytes());
|
||||
seq_writer.write_bytes(&lowerer.writer, &offset.to_le_bytes());
|
||||
seq_writer.write_bytes(&lowerer.writer, &(value.len() as u32).to_le_bytes());
|
||||
}
|
||||
IValue::ByteArray(values) => {
|
||||
let offset = lowerer.writer.write_bytes(&values)? as u32;
|
||||
|
||||
seq_writer.write_bytes(&offset.to_le_bytes());
|
||||
seq_writer.write_bytes(&(values.len() as u32).to_le_bytes());
|
||||
seq_writer.write_bytes(&lowerer.writer, &offset.to_le_bytes());
|
||||
seq_writer.write_bytes(&lowerer.writer, &(values.len() as u32).to_le_bytes());
|
||||
}
|
||||
IValue::Array(values) => {
|
||||
let LoweredArray { offset, size } = array_lower_memory(lowerer, values)?;
|
||||
|
||||
seq_writer.write_bytes(&(offset as u32).to_le_bytes());
|
||||
seq_writer.write_bytes(&(size as u32).to_le_bytes());
|
||||
seq_writer.write_bytes(&lowerer.writer, &(offset as u32).to_le_bytes());
|
||||
seq_writer.write_bytes(&lowerer.writer, &(size as u32).to_le_bytes());
|
||||
}
|
||||
IValue::Record(values) => {
|
||||
let offset = super::record_lower_memory(lowerer, values)? as u32;
|
||||
seq_writer.write_bytes(&offset.to_le_bytes());
|
||||
seq_writer.write_bytes(&lowerer.writer, &offset.to_le_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ use crate::traits::Allocatable;
|
||||
use crate::IValue;
|
||||
use crate::NEVec;
|
||||
|
||||
use it_memory_traits::SequentialMemoryView;
|
||||
use it_memory_traits::MemoryView;
|
||||
|
||||
pub fn record_lower_memory<A: Allocatable, MV: for<'a> SequentialMemoryView<'a>>(
|
||||
pub fn record_lower_memory<A: Allocatable<MV>, MV: MemoryView>(
|
||||
lowerer: &ILowerer<'_, A, MV>,
|
||||
values: NEVec<IValue>,
|
||||
) -> LoResult<u32> {
|
||||
|
@ -18,34 +18,103 @@ use super::LoResult;
|
||||
use crate::traits::Allocatable;
|
||||
use crate::utils::type_tag_form_itype;
|
||||
|
||||
use it_memory_traits::{SequentialMemoryView, SequentialWriter};
|
||||
use it_memory_traits::MemoryView;
|
||||
|
||||
pub struct MemoryWriter<'i, R: Allocatable, MV> {
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
pub struct MemoryWriter<'i, R: Allocatable<MV>, MV: MemoryView> {
|
||||
heap_manager: &'i R,
|
||||
view: MV,
|
||||
view: RefCell<MV>,
|
||||
}
|
||||
|
||||
impl<'i, A: Allocatable, MV: for<'a> SequentialMemoryView<'a>> MemoryWriter<'i, A, MV> {
|
||||
impl<'i, A: Allocatable<MV>, MV: MemoryView> MemoryWriter<'i, A, MV> {
|
||||
pub fn new(view: MV, heap_manager: &'i A) -> LoResult<Self> {
|
||||
let writer = Self { heap_manager, view };
|
||||
let writer = Self {
|
||||
heap_manager,
|
||||
view: RefCell::new(view),
|
||||
};
|
||||
Ok(writer)
|
||||
}
|
||||
|
||||
pub fn write_bytes(&self, bytes: &[u8]) -> LoResult<u32> {
|
||||
let byte_type_tag = type_tag_form_itype(&crate::IType::U8);
|
||||
let seq_writer = self.sequential_writer(bytes.len() as u32, byte_type_tag)?;
|
||||
seq_writer.write_bytes(bytes);
|
||||
seq_writer.write_bytes(&self, bytes);
|
||||
|
||||
Ok(seq_writer.start_offset())
|
||||
}
|
||||
|
||||
pub fn sequential_writer(
|
||||
&self,
|
||||
size: u32,
|
||||
type_tag: u32,
|
||||
) -> LoResult<<MV as SequentialMemoryView<'_>>::SW> {
|
||||
let offset = self.heap_manager.allocate(size, type_tag)?;
|
||||
let seq_writer = self.view.sequential_writer(offset, size)?;
|
||||
pub fn sequential_writer(&self, size: u32, type_tag: u32) -> LoResult<SequentialWriter> {
|
||||
let (offset, view) = self.heap_manager.allocate(size, type_tag)?;
|
||||
self.view.replace(view);
|
||||
let seq_writer = SequentialWriter::new(offset);
|
||||
Ok(seq_writer)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SequentialWriter {
|
||||
start_offset: u32,
|
||||
offset: Cell<u32>,
|
||||
}
|
||||
|
||||
impl SequentialWriter {
|
||||
pub(self) fn new(offset: u32) -> Self {
|
||||
Self {
|
||||
offset: Cell::new(offset),
|
||||
start_offset: offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_offset(&self) -> u32 {
|
||||
self.start_offset
|
||||
}
|
||||
|
||||
pub fn write_array<MV: MemoryView, A: Allocatable<MV>, const N: usize>(
|
||||
&self,
|
||||
writer: &MemoryWriter<'_, A, MV>,
|
||||
values: [u8; N],
|
||||
) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
writer.view.borrow().write_bytes(offset, &values);
|
||||
|
||||
self.offset.set(offset + N as u32);
|
||||
}
|
||||
|
||||
pub fn write_u8<MV: MemoryView, A: Allocatable<MV>>(
|
||||
&self,
|
||||
writer: &MemoryWriter<'_, A, MV>,
|
||||
value: u8,
|
||||
) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
writer.view.borrow().write_byte(offset, value);
|
||||
|
||||
self.offset.set(offset + 1);
|
||||
}
|
||||
|
||||
pub fn write_u32<MV: MemoryView, A: Allocatable<MV>>(
|
||||
&self,
|
||||
writer: &MemoryWriter<'_, A, MV>,
|
||||
value: u32,
|
||||
) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
let value = value.to_le_bytes();
|
||||
writer.view.borrow().write_bytes(offset, &value);
|
||||
|
||||
self.offset.set(offset + 4);
|
||||
}
|
||||
|
||||
pub fn write_bytes<MV: MemoryView, A: Allocatable<MV>>(
|
||||
&self,
|
||||
writer: &MemoryWriter<'_, A, MV>,
|
||||
bytes: &[u8],
|
||||
) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
writer.view.borrow().write_bytes(offset, bytes);
|
||||
|
||||
self.offset.set(offset + bytes.len() as u32);
|
||||
}
|
||||
}
|
||||
|
@ -27,15 +27,15 @@ pub use lower_array::array_lower_memory;
|
||||
pub use lower_array::LoweredArray;
|
||||
pub use lower_record::record_lower_memory;
|
||||
|
||||
pub use it_memory_traits::SequentialMemoryView;
|
||||
pub use it_memory_traits::MemoryView;
|
||||
|
||||
pub type LoResult<T> = std::result::Result<T, error::LoError>;
|
||||
|
||||
pub struct ILowerer<'m, A: Allocatable, MV> {
|
||||
pub struct ILowerer<'m, A: Allocatable<MV>, MV: MemoryView> {
|
||||
pub writer: MemoryWriter<'m, A, MV>,
|
||||
}
|
||||
|
||||
impl<'m, A: Allocatable, MV: for<'a> SequentialMemoryView<'a>> ILowerer<'m, A, MV> {
|
||||
impl<'m, A: Allocatable<MV>, MV: MemoryView> ILowerer<'m, A, MV> {
|
||||
pub fn new(view: MV, allocatable: &'m A) -> LoResult<Self> {
|
||||
let writer = MemoryWriter::new(view, allocatable)?;
|
||||
let lowerer = Self { writer };
|
||||
|
@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use it_memory_traits::MemoryView;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
pub const DEFAULT_MEMORY_INDEX: usize = 0;
|
||||
|
||||
pub trait Allocatable {
|
||||
fn allocate(&self, size: u32, type_tag: u32) -> Result<u32, AllocatableError>;
|
||||
pub trait Allocatable<MV: MemoryView> {
|
||||
fn allocate(&self, size: u32, type_tag: u32) -> Result<(u32, MV), AllocatableError>;
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "it-memory-traits"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
authors = ["Fluence Labs"]
|
||||
description = "Defines traits that IT uses for accessing memory"
|
||||
edition = "2018"
|
||||
|
@ -18,61 +18,44 @@ mod errors;
|
||||
|
||||
pub use errors::MemoryAccessError;
|
||||
|
||||
macro_rules! read_ty {
|
||||
($func_name:ident, $ty:ty, $size:literal) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
<$ty>::from_le_bytes(self.read_bytes::<$size>())
|
||||
}
|
||||
};
|
||||
pub trait MemoryReadable {
|
||||
/// This function will panic if the `offset` is out of bounds.
|
||||
/// It is caller's responsibility to check if the offset is in bounds
|
||||
/// using `MemoryView::check_bounds` function
|
||||
fn read_byte(&self, offset: u32) -> u8;
|
||||
|
||||
/// This function will panic if `[offset..offset + COUNT]` is out of bounds.
|
||||
/// It is caller's responsibility to check if the offset is in bounds
|
||||
/// using `MemoryView::check_bounds` function.
|
||||
fn read_array<const COUNT: usize>(&self, offset: u32) -> [u8; COUNT];
|
||||
|
||||
/// This function will panic if `[offset..offset + size]` is out of bounds.
|
||||
/// It is caller's responsibility to check if the offset is in bounds
|
||||
/// using `MemoryView::check_bounds` function.
|
||||
fn read_vec(&self, offset: u32, size: u32) -> Vec<u8>;
|
||||
}
|
||||
|
||||
pub trait SequentialReader {
|
||||
fn read_byte(&self) -> u8;
|
||||
pub trait MemoryWritable {
|
||||
/// This function will panic if `offset` is out of bounds.
|
||||
/// It is caller's responsibility to check if the offset is in bounds
|
||||
/// using `MemoryView::check_bounds` function.
|
||||
fn write_byte(&self, offset: u32, value: u8);
|
||||
|
||||
fn read_bytes<const COUNT: usize>(&self) -> [u8; COUNT];
|
||||
|
||||
fn read_bool(&self) -> bool {
|
||||
self.read_byte() != 0
|
||||
}
|
||||
|
||||
read_ty!(read_u8, u8, 1);
|
||||
read_ty!(read_i8, i8, 1);
|
||||
read_ty!(read_u16, u16, 2);
|
||||
read_ty!(read_i16, i16, 2);
|
||||
read_ty!(read_u32, u32, 4);
|
||||
read_ty!(read_i32, i32, 4);
|
||||
read_ty!(read_f32, f32, 4);
|
||||
read_ty!(read_u64, u64, 8);
|
||||
read_ty!(read_i64, i64, 8);
|
||||
read_ty!(read_f64, f64, 8);
|
||||
/// This function will panic if `[offset..offset + bytes.len()]`.is out of bounds.
|
||||
/// It is caller's responsibility to check if the offset is in bounds
|
||||
/// using `MemoryView::check_bounds` function.
|
||||
fn write_bytes(&self, offset: u32, bytes: &[u8]);
|
||||
}
|
||||
|
||||
pub trait SequentialWriter {
|
||||
fn start_offset(&self) -> u32;
|
||||
|
||||
// specialization of write_array for u8
|
||||
fn write_u8(&self, value: u8);
|
||||
|
||||
// specialization of write_array for u32
|
||||
fn write_u32(&self, value: u32);
|
||||
|
||||
fn write_bytes(&self, bytes: &[u8]);
|
||||
}
|
||||
|
||||
// the lifetime is needed because some implementations
|
||||
// need to bind SR and SW lifetimes to lifetime of &self in methods
|
||||
pub trait SequentialMemoryView<'s> {
|
||||
type SR: SequentialReader + 's;
|
||||
type SW: SequentialWriter + 's;
|
||||
|
||||
fn sequential_writer(&'s self, offset: u32, size: u32) -> Result<Self::SW, MemoryAccessError>;
|
||||
|
||||
fn sequential_reader(&'s self, offset: u32, size: u32) -> Result<Self::SR, MemoryAccessError>;
|
||||
pub trait MemoryView: MemoryWritable + MemoryReadable {
|
||||
/// For optimization purposes, user must check bounds first, then try read-write to memory
|
||||
/// `MemoryWritable` and `MemoryReadable` functions will panic in case of out of bounds access`
|
||||
fn check_bounds(&self, offset: u32, size: u32) -> Result<(), MemoryAccessError>;
|
||||
}
|
||||
|
||||
pub trait Memory<View>
|
||||
where
|
||||
View: for<'a> SequentialMemoryView<'a>,
|
||||
View: MemoryView,
|
||||
{
|
||||
fn view(&self) -> View;
|
||||
}
|
||||
|
Reference in New Issue
Block a user