1use crate::{contract_def::HasEvents, prelude::*};
10use core::cell::OnceCell;
11
12use crate::contract_env::ContractEnv;
13use core::ops::{Deref, DerefMut};
14
15pub trait Module {
17 fn new(env: Rc<ContractEnv>) -> Self;
19
20 fn env(&self) -> Rc<ContractEnv>;
22}
23
24pub trait ModuleComponent {
26 fn instance(env: Rc<ContractEnv>, index: u8) -> Self;
28}
29
30pub trait Revertible {
32 fn revert<E: Into<OdraError>>(&self, error: E) -> !;
34}
35
36impl Revertible for Rc<ContractEnv> {
37 fn revert<E: Into<OdraError>>(&self, error: E) -> ! {
38 self.as_ref().revert(error)
39 }
40}
41
42impl<T: Module> Revertible for T {
43 fn revert<E: Into<OdraError>>(&self, error: E) -> ! {
44 self.env().revert(error)
45 }
46}
47
48pub trait ModulePrimitive: ModuleComponent {}
53
54pub struct SubModule<T> {
58 env: Rc<ContractEnv>,
59 module: OnceCell<T>,
60 index: u8
61}
62
63impl<T: Module> ModuleComponent for SubModule<T> {
64 fn instance(env: Rc<ContractEnv>, index: u8) -> Self {
65 Self {
66 env,
67 module: OnceCell::new(),
68 index
69 }
70 }
71}
72
73impl<M: ModulePrimitive> HasEvents for M {
74 fn events() -> Vec<crate::contract_def::Event> {
75 Vec::new()
76 }
77}
78
79impl<M: HasEvents> HasEvents for SubModule<M> {
80 fn events() -> Vec<crate::contract_def::Event> {
81 M::events()
82 }
83
84 fn event_schemas() -> crate::prelude::BTreeMap<String, casper_event_standard::Schema> {
85 M::event_schemas()
86 }
87}
88
89impl<T: Module> SubModule<T> {
91 pub fn module(&self) -> &T {
95 self.module
96 .get_or_init(|| T::new(Rc::new(self.env.child(self.index))))
97 }
98
99 pub fn module_mut(&mut self) -> &mut T {
103 if self.module.get().is_none() {
104 let _ = self.module();
105 }
106 self.module.get_mut().unwrap()
107 }
108}
109
110impl<T: Module> Deref for SubModule<T> {
111 type Target = T;
112
113 fn deref(&self) -> &Self::Target {
114 self.module()
115 }
116}
117
118impl<T: Module> DerefMut for SubModule<T> {
119 fn deref_mut(&mut self) -> &mut Self::Target {
120 self.module_mut()
121 }
122}