use std::ops::{
Deref,
DerefMut,
};
use fuel_asm::Word;
use fuel_types::ContractId;
use crate::{
consts::MEM_SIZE,
prelude::{
MemoryRange,
RuntimeError,
},
};
pub mod reg_key;
#[derive(Clone)]
pub struct CheckedMemConstLen<const LEN: usize>(MemoryRange);
#[derive(Clone)]
pub struct CheckedMemValue<T>(MemoryRange, core::marker::PhantomData<T>);
impl<T> CheckedMemValue<T> {
pub fn new<const SIZE: usize>(address: Word) -> Result<Self, RuntimeError> {
Ok(Self(
MemoryRange::new_const::<_, SIZE>(address)?,
core::marker::PhantomData,
))
}
pub fn try_from(self, memory: &[u8; MEM_SIZE]) -> Result<T, RuntimeError>
where
T: for<'a> TryFrom<&'a [u8]>,
RuntimeError: for<'a> From<<T as TryFrom<&'a [u8]>>::Error>,
{
Ok(T::try_from(&memory[self.0.usizes()])?)
}
pub fn start(&self) -> usize {
self.0.start
}
pub fn end(&self) -> usize {
self.0.end
}
#[cfg(test)]
pub fn inspect(self, memory: &[u8; MEM_SIZE]) -> T
where
T: std::io::Write + Default,
{
let mut t = T::default();
t.write_all(&memory[self.0.usizes()]).unwrap();
t
}
}
impl<const LEN: usize> CheckedMemConstLen<LEN> {
pub fn new(address: Word) -> Result<Self, RuntimeError> {
Ok(Self(MemoryRange::new_const::<_, LEN>(address)?))
}
pub fn read(self, memory: &[u8; MEM_SIZE]) -> &[u8; LEN] {
(&memory[self.0.usizes()]).try_into().expect(
"This is always correct as the address and LEN are checked on construction.",
)
}
pub fn write(self, memory: &mut [u8; MEM_SIZE]) -> &mut [u8; LEN] {
(&mut memory[self.0.usizes()]).try_into().expect(
"This is always correct as the address and LEN are checked on construction.",
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InstructionLocation {
pub context: Option<ContractId>,
pub offset: u64,
}
impl<const LEN: usize> Deref for CheckedMemConstLen<LEN> {
type Target = MemoryRange;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<const LEN: usize> DerefMut for CheckedMemConstLen<LEN> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}