1use crate::decoding::{AccountId, Decodable, decode, decode_amount_json, decode_issue_json};
2use crate::hashing::Hash256;
3use crate::mock_data::{DataSource, Keylet, MockData};
4use std::ffi::c_void;
5
6const LOCATOR_BUFFER_SIZE: usize = 64;
7const NUM_SLOTS: usize = 256;
8pub const XRPL_CONTRACT_DATA_SIZE: usize = 4096;
9
10#[allow(dead_code)]
11pub enum HostError {
12 InternalError = -1,
13 FieldNotFound = -2,
14 BufferTooSmall = -3,
15 NoArray = -4,
16 NotLeafField = -5,
17 LocatorMalformed = -6,
18 SlotOutRange = -7,
19 NoFreeSlots = -8,
20 EmptySlot = -9,
21 LedgerObjNotFound = -10,
22 InvalidDecoding = -11,
23 DataFieldTooLarge = -12,
24 PointerOutOfBound = -13, NoMemoryExported = -14, InvalidParams = -15,
27 InvalidAccount = -16,
28 InvalidField = -17,
29 IndexOutOfBounds = -18,
30 InvalidFloatInput = -19,
31 InvalidFloatComputation = -20,
32}
33
34impl From<i64> for HostError {
35 fn from(value: i64) -> Self {
36 match value {
37 -1 => HostError::InternalError,
38 -2 => HostError::FieldNotFound,
39 -3 => HostError::BufferTooSmall,
40 -4 => HostError::NoArray,
41 -5 => HostError::NotLeafField,
42 -6 => HostError::LocatorMalformed,
43 -7 => HostError::SlotOutRange,
44 -8 => HostError::NoFreeSlots,
45 -9 => HostError::EmptySlot,
46 -10 => HostError::LedgerObjNotFound,
47 -11 => HostError::InvalidDecoding,
48 -12 => HostError::DataFieldTooLarge,
49 -13 => HostError::PointerOutOfBound,
50 -14 => HostError::NoMemoryExported,
51 -15 => HostError::InvalidParams,
52 -16 => HostError::InvalidAccount,
53 -17 => HostError::InvalidField,
54 -18 => HostError::IndexOutOfBounds,
55 _ => HostError::InternalError, }
57 }
58}
59
60pub fn error_code_to_string(code: i64) -> &'static str {
71 let host_error: HostError = code.into();
73
74 match host_error {
76 HostError::InternalError => "INTERNAL_ERROR (-1)",
77 HostError::FieldNotFound => "FIELD_NOT_FOUND (-2)",
78 HostError::BufferTooSmall => "BUFFER_TOO_SMALL (-3)",
79 HostError::NoArray => "NO_ARRAY (-4)",
80 HostError::NotLeafField => "NOT_LEAF_FIELD (-5)",
81 HostError::LocatorMalformed => "LOCATOR_MALFORMED (-6)",
82 HostError::SlotOutRange => "SLOT_OUT_RANGE (-7)",
83 HostError::NoFreeSlots => "SLOTS_FULL (-8)",
84 HostError::EmptySlot => "EMPTY_SLOT (-9)",
85 HostError::LedgerObjNotFound => "LEDGER_OBJ_NOT_FOUND (-10)",
86 HostError::InvalidDecoding => "DECODING_ERROR (-11)",
87 HostError::DataFieldTooLarge => "DATA_FIELD_TOO_LARGE (-12)",
88 HostError::PointerOutOfBound => "POINTER_OUT_OF_BOUND (-13)",
89 HostError::NoMemoryExported => "NO_MEMORY_EXPORTED (-14)",
90 HostError::InvalidParams => "INVALID_PARAMS (-15)",
91 HostError::InvalidAccount => "INVALID_ACCOUNT (-16)",
92 HostError::InvalidField => "INVALID_FIELD (-17)",
93 HostError::IndexOutOfBounds => "INDEX_OUT_OF_BOUNDS (-18)",
94 HostError::InvalidFloatInput => "INVALID_FLOAT_INPUT (-19)",
95 HostError::InvalidFloatComputation => "INVALID_FLOAT_COMPUTATION (-20)",
96 }
97}
98
99pub struct LocatorUnpacker {
100 buffer: Vec<u8>,
101 cur_buffer_index: usize,
102}
103
104impl LocatorUnpacker {
105 pub fn from_bytes(buffer: Vec<u8>) -> Option<LocatorUnpacker> {
106 let packed_bytes: usize = buffer.len();
107 if packed_bytes > LOCATOR_BUFFER_SIZE
108 || packed_bytes == 0
109 || !packed_bytes.is_multiple_of(4)
110 {
111 None
112 } else {
113 Some(LocatorUnpacker {
114 buffer,
115 cur_buffer_index: 0,
116 })
117 }
118 }
119
120 pub fn unpack(&mut self) -> Option<i32> {
121 if self.cur_buffer_index + 4 > self.buffer.len() {
122 return None;
123 }
124 let mut bytes: [u8; 4] = [0u8; 4];
125 bytes.copy_from_slice(&self.buffer[self.cur_buffer_index..self.cur_buffer_index + 4]);
126 self.cur_buffer_index += 4;
127 Some(i32::from_le_bytes(bytes))
128 }
129}
130
131pub fn unpack_locator(buffer: Vec<u8>) -> Result<Vec<i32>, HostError> {
132 let mut unpacker = LocatorUnpacker::from_bytes(buffer).ok_or(HostError::LocatorMalformed)?;
133
134 let mut result = vec![];
135 while let Some(slot) = unpacker.unpack() {
136 result.push(slot);
137 }
138 Ok(result)
139}
140
141use num_derive::FromPrimitive;
142#[derive(FromPrimitive, Debug)]
143pub enum RippledRoundingMode {
144 ToNearest = 0,
145 TowardsZero = 1,
146 Downward = 2,
147 Upward = 3,
148}
149
150pub struct DataProvider {
151 data_source: MockData,
152 next_slot: usize,
153 slots: [Keylet; NUM_SLOTS],
154 pub _rounding_mode: RippledRoundingMode,
155}
156
157impl DataProvider {
158 pub fn new(data_source: MockData) -> Self {
159 let slots: [Hash256; 256] = core::array::from_fn(|_| Hash256::default());
160 Self {
161 data_source,
162 next_slot: 1,
163 slots,
164 _rounding_mode: RippledRoundingMode::ToNearest,
165 }
166 }
167
168 pub fn slot_set(&mut self, keylet: Keylet, mut slot: usize) -> i32 {
169 if slot == 0 {
170 if self.next_slot >= NUM_SLOTS {
171 return HostError::NoFreeSlots as i32;
172 }
173 slot = self.next_slot;
174 self.next_slot += 1;
175 } else if slot >= NUM_SLOTS {
176 return HostError::SlotOutRange as i32;
177 }
178
179 if self.data_source.obj_exist(&keylet) {
180 self.slots[slot] = keylet;
181 slot as i32
182 } else {
183 HostError::LedgerObjNotFound as i32
184 }
185 }
186
187 pub fn slot_get(&self, slot: usize) -> Option<&Keylet> {
188 if slot == 0 || slot >= self.next_slot {
189 None
190 } else {
191 Some(&self.slots[slot])
192 }
193 }
194
195 pub fn get_field_value(
196 &self,
197 source: DataSource,
198 idx_fields: Vec<i32>,
199 buf_cap: usize,
200 ) -> (i32, Vec<u8>) {
201 assert!(!idx_fields.is_empty());
202 let (last_sfield, field_result) = match self.data_source.get_field_value(source, idx_fields)
203 {
204 Ok(v) => v,
205 Err(e) => return (e as i32, vec![]),
206 };
207
208 Self::fill_buf(
209 Some(field_result),
210 buf_cap,
211 Decodable::from_sfield(last_sfield),
212 )
213 }
214
215 pub fn get_array_len(&self, source: DataSource, idx_fields: Vec<i32>) -> i32 {
216 let (_, value) = match self.data_source.get_field_value(source, idx_fields) {
217 Ok(v) => v,
218 Err(e) => return e as i32,
219 };
220 if value.is_array() {
221 value.as_array().unwrap().len() as i32
222 } else {
223 HostError::NoArray as i32
224 }
225 }
226
227 pub fn get_ledger_sqn(&self) -> i32 {
228 match self.data_source.get_ledger_sqn() {
229 Some(value) => {
230 if let Some(num) = value.as_i64() {
231 num as i32
232 } else {
233 HostError::InvalidDecoding as i32
234 }
235 }
236 None => HostError::InternalError as i32,
237 }
238 }
239
240 pub fn get_parent_ledger_time(&self) -> i32 {
241 match self.data_source.get_parent_ledger_time() {
242 Some(value) => {
243 if let Some(num) = value.as_i64() {
244 num as i32
245 } else {
246 HostError::InvalidDecoding as i32
247 }
248 }
249 None => HostError::InternalError as i32,
250 }
251 }
252
253 pub fn get_parent_ledger_hash(&self, buf_cap: usize) -> (i32, Vec<u8>) {
254 let field_result = self.data_source.get_parent_ledger_hash();
255 Self::fill_buf(field_result, buf_cap, Decodable::UINT256)
256 }
257
258 pub fn get_nft_uri(
259 &self,
260 nft_id: &Hash256,
261 account_id: &AccountId,
262 buf_cap: usize,
263 ) -> (i32, Vec<u8>) {
264 let field_result = self.data_source.get_nft_uri(nft_id, account_id);
265 Self::fill_buf(field_result, buf_cap, Decodable::AS_IS)
266 }
267
268 pub fn set_current_ledger_obj_data(&mut self, data: Vec<u8>) {
269 self.data_source.set_current_ledger_obj_data(data);
270 }
271
272 fn fill_buf(
273 field_result: Option<&serde_json::Value>,
274 buf_cap: usize,
275 decodable: Decodable,
276 ) -> (i32, Vec<u8>) {
277 let mut buf = vec![0u8; buf_cap];
278 match field_result {
279 Some(value) => {
280 if decodable == Decodable::AMOUNT {
281 match decode_amount_json(value.clone()) {
282 None => (HostError::InvalidDecoding as i32, buf),
283 Some(bytes) => {
284 if bytes.len() > buf_cap {
285 return (HostError::BufferTooSmall as i32, buf);
286 }
287 buf[..bytes.len()].copy_from_slice(&bytes);
288 (bytes.len() as i32, buf)
289 }
290 }
291 } else if decodable == Decodable::ISSUE {
292 match decode_issue_json(value.clone()) {
293 None => (HostError::InvalidDecoding as i32, buf),
294 Some(bytes) => {
295 if bytes.len() > buf_cap {
296 return (HostError::BufferTooSmall as i32, buf);
297 }
298 buf[..bytes.len()].copy_from_slice(&bytes);
299 (bytes.len() as i32, buf)
300 }
301 }
302 } else {
303 match value {
304 serde_json::Value::Number(n) => {
305 if n.is_i64() {
306 let num = n.as_i64().unwrap();
307 if buf_cap == 4 {
308 if num > u32::MAX as i64 || num < u32::MIN as i64 {
310 return (HostError::BufferTooSmall as i32, buf);
311 }
312 let bytes = (num as u32).to_le_bytes();
313 buf[..4].copy_from_slice(&bytes);
314 (4, buf)
315 } else {
316 let bytes = num.to_le_bytes();
317 if bytes.len() > buf_cap {
318 return (HostError::BufferTooSmall as i32, buf);
319 }
320 buf[..bytes.len()].copy_from_slice(&bytes);
321 (bytes.len() as i32, buf)
322 }
323 } else if n.is_u64() {
324 let num = n.as_u64().unwrap();
325 if buf_cap == 4 {
326 if num > u32::MAX as u64 {
328 return (HostError::BufferTooSmall as i32, buf);
329 }
330 let bytes = (num as u32).to_le_bytes();
331 buf[..4].copy_from_slice(&bytes);
332 (4, buf)
333 } else {
334 let bytes = num.to_le_bytes();
335 if bytes.len() > buf_cap {
336 return (HostError::BufferTooSmall as i32, buf);
337 }
338 buf[..bytes.len()].copy_from_slice(&bytes);
339 (bytes.len() as i32, buf)
340 }
341 } else if n.is_f64() {
342 let s = n.as_f64().unwrap().to_string();
343 let bytes = s.as_bytes();
344 if bytes.len() > buf_cap {
345 return (HostError::BufferTooSmall as i32, buf);
346 }
347 buf[..bytes.len()].copy_from_slice(bytes);
348 (bytes.len() as i32, buf)
349 } else {
350 (HostError::InternalError as i32, buf)
351 }
352 }
353 serde_json::Value::String(s) => match decode(s, decodable) {
354 None => (HostError::InvalidDecoding as i32, buf),
355 Some(bytes) => {
356 if bytes.len() > buf_cap {
357 return (HostError::BufferTooSmall as i32, buf);
358 }
359 buf[..bytes.len()].copy_from_slice(&bytes);
360 (bytes.len() as i32, buf)
361 }
362 },
363 serde_json::Value::Bool(b) => {
364 if buf_cap == 0 {
365 return (HostError::BufferTooSmall as i32, buf);
366 }
367 buf[0] = if *b { 1 } else { 0 };
368 (1, buf)
369 }
370 serde_json::Value::Null => (HostError::NotLeafField as i32, buf),
372 serde_json::Value::Array(_) => (HostError::NotLeafField as i32, buf),
373 serde_json::Value::Object(_) => (HostError::NotLeafField as i32, buf),
374 }
375 }
376 }
377 None => (HostError::FieldNotFound as i32, buf),
378 }
379 }
380 #[allow(unused)]
381 pub fn as_ptr(&mut self) -> *mut c_void {
382 self as *mut _ as *mut c_void
383 }
384}