ab_contracts_common/
env.rs1use crate::ContractError;
2use crate::method::{ExternalArgs, MethodFingerprint};
3use ab_core_primitives::address::Address;
4use ab_core_primitives::shard::ShardIndex;
5use ab_io_type::trivial_type::TrivialType;
6use core::ffi::c_void;
7use core::marker::PhantomData;
8use core::ptr::NonNull;
9
10#[derive(Debug, Copy, Clone, Eq, PartialEq, TrivialType)]
21#[repr(u8)]
22pub enum MethodContext {
23 Keep,
25 Reset,
27 Replace,
29}
30
31#[derive(Debug)]
33#[repr(C)]
34#[must_use]
35pub struct PreparedMethod<'a> {
36 pub contract: Address,
38 pub fingerprint: MethodFingerprint,
40 pub external_args: NonNull<NonNull<c_void>>,
43 pub method_context: MethodContext,
45 pub phantom: PhantomData<&'a ()>,
47}
48
49#[derive(Debug, Copy, Clone, TrivialType)]
51#[repr(C)]
52pub struct EnvState {
53 pub shard_index: ShardIndex,
55 pub padding_0: [u8; 4],
57 pub own_address: Address,
59 pub context: Address,
61 pub caller: Address,
63}
64
65#[cfg(feature = "executor")]
67pub trait ExecutorContext: core::fmt::Debug {
68 fn call(
70 &self,
71 previous_env_state: &EnvState,
72 prepared_methods: &mut PreparedMethod<'_>,
73 ) -> Result<(), ContractError>;
74}
75
76#[cfg(all(feature = "executor", feature = "guest", not(any(doc, unix, windows))))]
77compile_error!(
78 "`executor` and `guest` features are mutually exclusive due to it affecting `Env` layout"
79);
80
81#[derive(Debug)]
86#[repr(C)]
87pub struct Env<'a> {
88 state: EnvState,
89 #[cfg(feature = "executor")]
90 executor_context: &'a mut dyn ExecutorContext,
91 phantom_data: PhantomData<&'a ()>,
92}
93
94impl<'a> Env<'a> {
98 #[cfg(feature = "executor")]
100 #[inline(always)]
101 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
102 pub fn with_executor_context(
103 state: EnvState,
104 executor_context: &'a mut dyn ExecutorContext,
105 ) -> Self {
106 Self {
107 state,
108 executor_context,
109 phantom_data: PhantomData,
110 }
111 }
112
113 #[cfg(feature = "executor")]
115 #[inline(always)]
116 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
117 pub fn get_mut_executor_context(&mut self) -> &mut dyn ExecutorContext {
118 self.executor_context
119 }
120
121 #[inline(always)]
123 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
124 pub fn shard_index(&self) -> ShardIndex {
125 self.state.shard_index
126 }
127
128 #[inline(always)]
130 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
131 pub fn own_address(&self) -> Address {
132 self.state.own_address
133 }
134
135 #[inline(always)]
137 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
138 pub fn context<'b>(self: &'b &'b mut Self) -> Address {
139 self.state.context
140 }
141
142 #[inline(always)]
144 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
145 pub fn caller<'b>(self: &'b &'b mut Self) -> Address {
146 self.state.caller
147 }
148
149 #[inline(always)]
153 pub fn call<Args>(
154 &self,
155 contract: Address,
156 args: &mut Args,
157 method_context: MethodContext,
158 ) -> Result<(), ContractError>
159 where
160 Args: ExternalArgs,
161 {
162 let prepared_method = Self::prepare_method_call(contract, args, method_context);
163 self.call_prepared(prepared_method)
164 }
165
166 #[inline(always)]
170 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
171 pub fn prepare_method_call<Args>(
172 contract: Address,
173 args: &mut Args,
174 method_context: MethodContext,
175 ) -> PreparedMethod<'_>
176 where
177 Args: ExternalArgs,
178 {
179 PreparedMethod {
180 contract,
181 fingerprint: Args::FINGERPRINT,
182 external_args: NonNull::from_mut(args).cast::<NonNull<c_void>>(),
184 method_context,
185 phantom: PhantomData,
186 }
187 }
188
189 #[inline]
194 pub fn call_prepared(&self, method: PreparedMethod<'_>) -> Result<(), ContractError> {
195 #[cfg(feature = "executor")]
196 {
197 let mut method = method;
198 self.executor_context.call(&self.state, &mut method)
199 }
200 #[cfg(all(feature = "guest", not(feature = "executor")))]
201 {
202 let _ = method;
203 todo!()
204 }
205 #[cfg(not(any(feature = "executor", feature = "guest")))]
206 {
207 let _ = method;
208 Err(ContractError::InternalError)
209 }
210 }
211}