1use crate::casper_types::{
2 bytesrepr::{FromBytes, ToBytes},
3 CLTyped
4};
5use crate::contract_env::ContractEnv;
6use crate::module::{ModuleComponent, ModulePrimitive};
7use crate::prelude::*;
8
9pub struct Var<T> {
11 env: Rc<ContractEnv>,
12 phantom: core::marker::PhantomData<T>,
13 index: u8
14}
15
16impl<T> Revertible for Var<T> {
17 fn revert<E: Into<OdraError>>(&self, e: E) -> ! {
18 self.env.revert(e)
19 }
20}
21
22impl<T> Var<T> {
23 pub fn env(&self) -> ContractEnv {
25 self.env.child(self.index)
26 }
27}
28
29impl<T> ModuleComponent for Var<T> {
31 fn instance(env: Rc<ContractEnv>, index: u8) -> Self {
33 Self {
34 env,
35 phantom: core::marker::PhantomData,
36 index
37 }
38 }
39}
40
41impl<T> ModulePrimitive for Var<T> {}
42
43impl<T: FromBytes> Var<T> {
44 pub fn get(&self) -> Option<T> {
48 let env = self.env();
49 env.get_value(&env.current_key())
50 }
51
52 pub fn get_or_revert_with<E: Into<OdraError>>(&self, error: E) -> T {
56 self.get().unwrap_or_revert_with(self, error)
57 }
58}
59
60impl<T: FromBytes + Default> Var<T> {
61 pub fn get_or_default(&self) -> T {
63 self.get().unwrap_or_default()
64 }
65}
66
67impl<T: ToBytes + CLTyped> Var<T> {
68 pub fn set(&mut self, value: T) {
70 let env = self.env();
71 env.set_value(&env.current_key(), value);
72 }
73}
74
75impl<V: ToBytes + FromBytes + CLTyped + OverflowingAdd + Default> Var<V> {
76 #[inline(always)]
81 pub fn add(&mut self, value: V) {
82 let env = self.env();
83 let key = env.current_key();
84 let current_value = env.get_value::<V>(&key).unwrap_or_default();
85 let new_value = current_value.overflowing_add(value).unwrap_or_revert(self);
86 env.set_value(&key, new_value);
87 }
88}
89
90impl<V: ToBytes + FromBytes + CLTyped + OverflowingSub + Default> Var<V> {
91 #[inline(always)]
96 pub fn subtract(&mut self, value: V) {
97 let env = self.env();
98 let key = env.current_key();
99 let current_value = env.get_value::<V>(&key).unwrap_or_default();
100 let new_value = current_value.overflowing_sub(value).unwrap_or_revert(self);
101 env.set_value(&key, new_value);
102 }
103}