use crate::arithmetic::{OverflowingAdd, OverflowingSub};
use crate::casper_types::{
bytesrepr::{FromBytes, ToBytes},
CLTyped
};
use crate::module::{ModuleComponent, ModulePrimitive, Revertible};
use crate::{
module::{Module, SubModule},
var::Var,
ContractEnv
};
use crate::{prelude::*, OdraError};
use core::fmt::Debug;
pub struct Mapping<K, V> {
parent_env: Rc<ContractEnv>,
phantom: core::marker::PhantomData<(K, V)>,
index: u8
}
impl<K: ToBytes, V> ModuleComponent for Mapping<K, V> {
fn instance(env: Rc<ContractEnv>, index: u8) -> Self {
Self {
parent_env: env,
phantom: core::marker::PhantomData,
index
}
}
}
impl<K: ToBytes, V> Revertible for Mapping<K, V> {
fn revert<E: Into<OdraError>>(&self, e: E) -> ! {
self.parent_env.revert(e)
}
}
impl<K: ToBytes, V> ModulePrimitive for Mapping<K, V> {}
impl<K: ToBytes, V> Mapping<K, V> {
fn env_for_key(&self, key: &K) -> ContractEnv {
let mut env = (*self.parent_env).clone();
let key = key.to_bytes().unwrap_or_default();
env.add_to_mapping_data(&key);
env
}
}
impl<K: ToBytes, V: FromBytes + CLTyped> Mapping<K, V> {
pub fn get(&self, key: &K) -> Option<V> {
let env = self.env_for_key(key);
Var::<V>::instance(Rc::new(env), self.index).get()
}
}
impl<K: ToBytes, V: FromBytes + CLTyped + Default> Mapping<K, V> {
pub fn get_or_default(&self, key: &K) -> V {
let env = self.env_for_key(key);
Var::<V>::instance(Rc::new(env), self.index).get_or_default()
}
}
impl<K: ToBytes, V: ToBytes + CLTyped> Mapping<K, V> {
pub fn set(&mut self, key: &K, value: V) {
let env = self.env_for_key(key);
Var::<V>::instance(Rc::new(env), self.index).set(value)
}
}
impl<K: ToBytes, V: Module> Mapping<K, V> {
pub fn module(&self, key: &K) -> SubModule<V> {
let env = self.env_for_key(key);
SubModule::instance(Rc::new(env), self.index)
}
}
impl<K: ToBytes, V: ToBytes + FromBytes + CLTyped + OverflowingAdd + Default> Mapping<K, V> {
pub fn add(&mut self, key: &K, value: V) {
let env = self.env_for_key(key);
let mut var = Var::<V>::instance(Rc::new(env), self.index);
var.add(value);
}
}
impl<
K: ToBytes,
V: ToBytes + FromBytes + CLTyped + OverflowingSub + Default + Debug + PartialOrd
> Mapping<K, V>
{
pub fn subtract(&mut self, key: &K, value: V) {
let env = self.env_for_key(key);
let mut var = Var::<V>::instance(Rc::new(env), self.index);
var.subtract(value);
}
}