1mod error;
5mod externf;
6mod value_wrapper;
7use borsh::{BorshDeserialize, BorshSerialize};
8use error::Error;
9use serde::{Deserialize, Serialize};
10
11pub use self::value_wrapper::ValueWrapper;
12
13#[derive(Serialize, Deserialize, Debug)]
15pub struct Context<Event> {
16 pub event: Event,
18 pub is_owner: bool,
20}
21
22#[derive(Serialize, Deserialize, Debug)]
24pub struct ContractResult<State> {
25 pub state: State,
27 pub success: bool,
29 pub error: String
31}
32
33#[derive(Serialize, Deserialize, Debug, Default)]
35pub struct ContractInitCheck {
36 pub success: bool,
38 pub error: String,
40}
41
42#[derive(BorshSerialize)]
44struct ContractResultBorsh {
45 pub final_state: ValueWrapper,
47 pub success: bool,
49 pub error: String
51}
52
53impl ContractResultBorsh {
55 pub fn error(error: &str) -> Self {
56 Self {
57 final_state: ValueWrapper(serde_json::Value::Null),
58 success: false,
59 error: error.to_owned()
60 }
61 }
62}
63
64#[derive(BorshSerialize)]
66struct ContractInitCheckBorsh {
67 pub success: bool,
69 pub error: String
71}
72
73impl ContractInitCheckBorsh {
75 pub fn error(error: &str) -> Self {
76 Self {
77 success: false,
78 error: error.to_owned()
79 }
80 }
81
82 pub fn ok() -> Self {
83 Self {
84 success: true,
85 error: String::default()
86 }
87 }
88}
89
90impl<State> ContractResult<State> {
92 pub fn new(state: State) -> Self {
93 Self {
94 state,
95 success: false,
96 error: String::default()
97 }
98 }
99}
100
101pub fn check_init_data<State, F>(
113 state_ptr: i32,
114 callback: F,
115) -> u32
116where
117 State: for<'a> Deserialize<'a> + Serialize + Clone,
118 F: Fn(&State, &mut ContractInitCheck),
119{
120 {
121 let error: String;
122 'process: {
123 let Ok(state_value) = deserialize(get_from_context(state_ptr)) else {
124 error = "Can not deserialize State".to_owned();
125 break 'process;
126 };
127 let Ok(state) = serde_json::from_value::<State>(state_value.0) else {
128 error = "Can not convert State from value".to_owned();
129 break 'process;
130 };
131 let mut contract_result = ContractInitCheck::default();
132 callback(&state, &mut contract_result);
133
134 if !contract_result.success {
135 error = format!("Error running init contract data: {}", contract_result.error);
136 break 'process;
137 }
138
139 let Ok(result_ptr) = store(&ContractInitCheckBorsh::ok()) else {
140 error = "Can not return init contract result".to_owned();
141 break 'process;
142 };
143 return result_ptr;
144 }
145 store(&ContractInitCheckBorsh::error(&error)).expect("Contract store process failed")
146 }
147}
148
149pub fn execute_contract<F, State, Event>(
163 state_ptr: i32,
164 init_state_ptr: i32,
165 event_ptr: i32,
166 is_owner: i32,
167 callback: F,
168) -> u32
169where
170 State: for<'a> Deserialize<'a> + Serialize + Clone,
171 Event: for<'a> Deserialize<'a> + Serialize,
172 F: Fn(&Context<Event>, &mut ContractResult<State>),
173{
174 {
175 let error: String;
176 'process: {
177 let Ok(state_value) = deserialize(get_from_context(state_ptr)) else {
178 error = "Can not deserialize State".to_owned();
179 break 'process;
180 };
181 let state = match serde_json::from_value::<State>(state_value.0) {
182 Ok(state) => state,
183 Err(_) => {
184 let Ok(init_state) = deserialize(get_from_context(init_state_ptr)) else {
185 error = "Can not deserialize Init State".to_owned();
186 break 'process;
187 };
188
189 let Ok(init_state) = serde_json::from_value::<State>(init_state.0) else {
190 error = "Can not convert State from value".to_owned();
191 break 'process;
192 };
193
194 init_state
195 }
196 };
197 let Ok(event_value) = deserialize(get_from_context(event_ptr)) else {
198 error = "Can not deserialize Event".to_owned();
199 break 'process;
200 };
201 let Ok(event) = serde_json::from_value::<Event>(event_value.0) else {
202 error = "Can not convert Event from value".to_owned();
203 break 'process;
204 };
205 let is_owner = if is_owner == 1 { true } else { false };
206 let context = Context {
207 event,
208 is_owner
209 };
210 let mut contract_result = ContractResult::new(state);
211 callback(&context, &mut contract_result);
212 let Ok(state_value) = serde_json::to_value(&contract_result.state) else {
213 error = "Can not convert contract final state into Value".to_owned();
214 break 'process;
215 };
216 let result = ContractResultBorsh {
217 final_state: ValueWrapper(state_value),
218 success: contract_result.success,
219 error: format!("Error running contract event: {}", contract_result.error)
220 };
221 let Ok(result_ptr) = store(&result) else {
224 error = "Can not return contract result".to_owned();
225 break 'process;
226 };
227 return result_ptr;
228 };
229 store(&ContractResultBorsh::error(&error)).expect("Contract store process failed")
230 }
231}
232
233fn deserialize(bytes: Vec<u8>) -> Result<ValueWrapper, Error> {
234 BorshDeserialize::try_from_slice(&bytes).map_err(|e| Error::Deserialization(e.to_string()))
235}
236
237fn serialize<S: BorshSerialize>(data: S) -> Result<Vec<u8>, Error> {
238 borsh::to_vec(&data).map_err(|e| Error::Serialization(e.to_string()))
239}
240
241fn get_from_context(pointer: i32) -> Vec<u8> {
242 let data = unsafe {
243 let len = externf::pointer_len(pointer);
244 let mut data = vec![];
245 for i in 0..len {
246 data.push(externf::read_byte(pointer + i));
247 }
248 data
249 };
250 data
251}
252
253fn store<S>(data: &S) -> Result<u32, Error>
254where
255 S: BorshSerialize
256{
257 let bytes = serialize(&data).map_err(|e| Error::Serialization(e.to_string()))?;
258 unsafe {
259 let ptr = externf::alloc(bytes.len() as u32) as u32;
260 for (index, byte) in bytes.into_iter().enumerate() {
261 externf::write_byte(ptr, index as u32, byte);
262 }
263 Ok(ptr)
264 }
265}
266
267#[cfg(test)]
268mod tests {
269}