Refactor memory access interface to fix that writer does not update memory after allocation (#17)

This commit is contained in:
Valery Antopol
2022-04-06 22:25:01 +03:00
committed by GitHub
parent cbdea8e362
commit b233bfcadd
25 changed files with 372 additions and 350 deletions

View File

@ -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"

View File

@ -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;
}