use fuel_storage::Mappable;
use fuel_tx::Contract;
use fuel_types::{AssetId, Bytes32, ContractId, Salt, Word};
mod interpreter;
mod memory;
mod predicate;
pub use interpreter::InterpreterStorage;
pub use memory::MemoryStorage;
pub use predicate::PredicateStorage;
pub struct ContractsRawCode;
impl Mappable for ContractsRawCode {
type Key = Self::OwnedKey;
type OwnedKey = ContractId;
type Value = [u8];
type OwnedValue = Contract;
}
pub struct ContractsInfo;
impl Mappable for ContractsInfo {
type Key = Self::OwnedKey;
type OwnedKey = ContractId;
type Value = (Salt, Bytes32);
type OwnedValue = Self::Value;
}
pub struct ContractsAssets;
impl Mappable for ContractsAssets {
type Key = Self::OwnedKey;
type OwnedKey = ContractsAssetKey;
type Value = Word;
type OwnedValue = Self::Value;
}
pub struct ContractsState;
impl Mappable for ContractsState {
type Key = Self::OwnedKey;
type OwnedKey = ContractsStateKey;
type Value = Bytes32;
type OwnedValue = Self::Value;
}
macro_rules! double_key {
($i:ident, $first:ident, $first_getter:ident, $second:ident, $second_getter:ident) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $i([u8; { $first::LEN + $second::LEN }]);
impl Default for $i {
fn default() -> Self {
Self([0; { Self::second_end() }])
}
}
impl $i {
pub const LEN: usize = $first::LEN + $second::LEN;
pub fn new(first: &$first, second: &$second) -> Self {
let mut default = Self::default();
default.0[0..Self::first_end()].copy_from_slice(first.as_ref());
default.0[Self::first_end()..Self::second_end()].copy_from_slice(second.as_ref());
default
}
pub fn from_array(array: [u8; { $first::LEN + $second::LEN }]) -> Self {
Self(array)
}
pub fn from_slice(slice: &[u8]) -> Result<Self, core::array::TryFromSliceError> {
Ok(Self(slice.try_into()?))
}
pub fn $first_getter(&self) -> &$first {
unsafe { $first::as_ref_unchecked(&self.0[0..Self::first_end()]) }
}
pub fn $second_getter(&self) -> &$second {
unsafe { $second::as_ref_unchecked(&self.0[Self::first_end()..Self::second_end()]) }
}
const fn first_end() -> usize {
$first::LEN
}
const fn second_end() -> usize {
$first::LEN + $second::LEN
}
}
impl From<(&$first, &$second)> for $i {
fn from(pair: (&$first, &$second)) -> Self {
Self::new(pair.0, pair.1)
}
}
impl AsRef<[u8]> for $i {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl From<$i> for ($first, $second) {
fn from(key: $i) -> ($first, $second) {
let first = &key.0[0..$i::first_end()];
let second = &key.0[$i::first_end()..$i::second_end()];
let first = first.try_into().unwrap();
let second = second.try_into().unwrap();
(first, second)
}
}
impl From<$i> for [u8; { $first::LEN + $second::LEN }] {
fn from(key: $i) -> [u8; { $first::LEN + $second::LEN }] {
key.0
}
}
};
}
double_key!(ContractsAssetKey, ContractId, contract_id, AssetId, asset_id);
double_key!(ContractsStateKey, ContractId, contract_id, Bytes32, state_key);