use std::error::Error;
use namada_gas::Gas;
pub trait VmMemory: Clone + Send + Sync {
type Error: Error + Sync + Send + 'static + Into<namada_state::Error>;
fn read_bytes(
&mut self,
offset: u64,
len: usize,
) -> Result<(Vec<u8>, Gas), Self::Error>;
fn write_bytes(
&mut self,
offset: u64,
bytes: impl AsRef<[u8]>,
) -> Result<Gas, Self::Error>;
fn read_string(
&mut self,
offset: u64,
len: usize,
) -> Result<(String, Gas), Self::Error>;
fn write_string(
&mut self,
offset: u64,
string: String,
) -> Result<Gas, Self::Error>;
}
#[cfg(feature = "testing")]
pub mod testing {
pub use core::slice;
use std::convert::Infallible;
use super::*;
#[derive(Clone, Default)]
pub struct NativeMemory;
type Result<T> = std::result::Result<T, Infallible>;
impl VmMemory for NativeMemory {
type Error = Infallible;
fn read_bytes(
&mut self,
offset: u64,
len: usize,
) -> Result<(Vec<u8>, Gas)> {
let slice = unsafe { slice::from_raw_parts(offset as _, len as _) };
Ok((slice.to_vec(), Gas::default()))
}
fn write_bytes(
&mut self,
offset: u64,
bytes: impl AsRef<[u8]>,
) -> Result<Gas> {
let bytes = bytes.as_ref();
let len = bytes.len();
let target =
unsafe { slice::from_raw_parts_mut(offset as _, len as _) };
target.clone_from_slice(bytes);
Ok(Gas::default())
}
fn read_string(
&mut self,
offset: u64,
len: usize,
) -> Result<(String, Gas)> {
let slice = unsafe { slice::from_raw_parts(offset as _, len as _) };
let string = std::str::from_utf8(slice)
.expect("unable to decode string from memory")
.to_string();
Ok((string, Gas::default()))
}
fn write_string(&mut self, offset: u64, string: String) -> Result<Gas> {
let bytes = string.as_bytes();
let len = bytes.len();
let target =
unsafe { slice::from_raw_parts_mut(offset as _, len as _) };
target.clone_from_slice(bytes);
Ok(Gas::default())
}
}
}