use core::ops::{
Deref,
DerefMut,
};
use fuel_asm::{
PanicReason,
Word,
};
use fuel_types::ContractId;
#[cfg(test)]
use fuel_types::canonical::Deserialize;
use crate::{
consts::MEM_SIZE,
prelude::MemoryRange,
};
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, PanicReason> {
Ok(Self(
MemoryRange::new_const::<_, SIZE>(address)?,
core::marker::PhantomData,
))
}
pub fn try_from(self, memory: &[u8; MEM_SIZE]) -> Result<T, PanicReason>
where
T: for<'a> TryFrom<&'a [u8]>,
PanicReason: 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: Deserialize,
{
T::from_bytes(&memory[self.0.usizes()])
.expect("Inspect failed; invalid value for type")
}
}
impl<const LEN: usize> CheckedMemConstLen<LEN> {
pub fn new(address: Word) -> Result<Self, PanicReason> {
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
}
}