1use std::{collections::HashMap, fmt};
2
3use primitive_types::{H160, H256};
8use serde::{
9 de::{Unexpected, Visitor},
10 Deserialize, Deserializer, Serialize,
11};
12
13use crate::crypto::Secp256r1PublicKey;
14use neo3::prelude::{Address, ScriptHashExtension};
15
16#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
18#[serde(tag = "type")]
19pub enum StackItem {
20 #[serde(rename = "Any")]
22 Any,
23
24 #[serde(rename = "Pointer")]
26 Pointer {
27 #[serde(deserialize_with = "deserialize_integer_from_string")]
28 value: i64,
29 },
30
31 #[serde(rename = "Boolean")]
33 Boolean { value: bool },
34
35 #[serde(rename = "Integer")]
37 Integer {
38 #[serde(deserialize_with = "deserialize_integer_from_string")]
39 value: i64,
40 },
41
42 #[serde(rename = "ByteString")]
44 ByteString {
45 value: String, },
47
48 #[serde(rename = "Buffer")]
50 Buffer {
51 value: String, },
53
54 #[serde(rename = "Array")]
56 Array { value: Vec<StackItem> },
57
58 #[serde(rename = "Struct")]
60 Struct { value: Vec<StackItem> },
61
62 #[serde(rename = "Map")]
64 Map { value: Vec<MapEntry> },
65
66 #[serde(rename = "InteropInterface")]
68 InteropInterface { id: String, interface: String },
69}
70
71fn deserialize_integer_from_string<'de, D>(deserializer: D) -> Result<i64, D::Error>
72where
73 D: Deserializer<'de>,
74{
75 struct StringOrIntVisitor;
79
80 impl<'de> Visitor<'de> for StringOrIntVisitor {
81 type Value = i64;
82
83 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
84 formatter.write_str("a string or integer")
85 }
86
87 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
88 where
89 E: serde::de::Error,
90 {
91 value.parse::<i64>().map_err(serde::de::Error::custom)
92 }
93
94 fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
95 where
96 E: serde::de::Error,
97 {
98 value.parse::<i64>().map_err(serde::de::Error::custom)
99 }
100
101 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
102 where
103 E: serde::de::Error,
104 {
105 Ok(value)
106 }
107
108 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
109 where
110 E: serde::de::Error,
111 {
112 Ok(value as i64)
113 }
114 }
115
116 deserializer.deserialize_any(StringOrIntVisitor)
117}
118
119#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
121pub struct MapEntry {
122 key: StackItem,
123 value: StackItem,
124}
125
126impl StackItem {
127 pub const ANY_VALUE: &'static str = "Any";
129
130 pub const POINTER_VALUE: &'static str = "Pointer";
132
133 pub const BOOLEAN_VALUE: &'static str = "Boolean";
135
136 pub const INTEGER_VALUE: &'static str = "Integer";
138
139 pub const BYTE_STRING_VALUE: &'static str = "ByteString";
141
142 pub const BUFFER_VALUE: &'static str = "Buffer";
144
145 pub const ARRAY_VALUE: &'static str = "Array";
147
148 pub const STRUCT_VALUE: &'static str = "Struct";
150
151 pub const MAP_VALUE: &'static str = "Map";
153
154 pub const INTEROP_INTERFACE_VALUE: &'static str = "InteropInterface";
156
157 pub const ANY_BYTE: u8 = 0x00;
159
160 pub const POINTER_BYTE: u8 = 0x10;
162
163 pub const BOOLEAN_BYTE: u8 = 0x20;
165
166 pub const INTEGER_BYTE: u8 = 0x21;
168
169 pub const BYTE_STRING_BYTE: u8 = 0x28;
171
172 pub const BUFFER_BYTE: u8 = 0x30;
174
175 pub const ARRAY_BYTE: u8 = 0x40;
177
178 pub const STRUCT_BYTE: u8 = 0x41;
180
181 pub const MAP_BYTE: u8 = 0x48;
183
184 pub const INTEROP_INTERFACE_BYTE: u8 = 0x60;
186
187 pub fn new_byte_string(byte_array: Vec<u8>) -> Self {
188 let byte_string = base64::encode(byte_array);
189 StackItem::ByteString { value: byte_string }
190 }
191
192 pub fn as_bool(&self) -> Option<bool> {
194 match self {
195 StackItem::Boolean { value } => Some(*value),
196 StackItem::Integer { value } => Some(value != &0),
197 _ => None,
198 }
199 }
200
201 pub fn as_string(&self) -> Option<String> {
203 match self {
204 StackItem::ByteString { value } | StackItem::Buffer { value } => {
205 Some(String::from_utf8_lossy(&base64::decode(value).unwrap()).to_string())
206 },
207 StackItem::Integer { value } => Some(value.to_string()),
208 StackItem::Boolean { value } => Some(value.to_string()),
209 _ => None,
210 }
211 }
212
213 pub fn to_string(&self) -> String {
215 match self {
216 StackItem::Any => "Any".to_string(),
217 StackItem::Pointer { value: pointer } => format!("Pointer{{value={}}}", pointer),
218 StackItem::Boolean { value: boolean } => format!("Boolean{{value={}}}", boolean),
219 StackItem::Integer { value: integer } => format!("Integer{{value={}}}", integer),
220 StackItem::ByteString { value: byteString } => {
221 format!("ByteString{{value={:?}}}", byteString)
222 },
223 StackItem::Buffer { value: buffer } => format!("Buffer{{value={:?}}}", buffer),
224 StackItem::Array { value: array } => {
225 let values = array.iter().map(StackItem::to_string).collect::<Vec<_>>().join(", ");
226 format!("Array{{value=[{}]}}", values)
227 },
228 StackItem::Struct { value: _struct } => {
229 let values =
230 _struct.iter().map(StackItem::to_string).collect::<Vec<_>>().join(", ");
231 format!("Struct{{value=[{}]}}", values)
232 },
233 StackItem::Map { value: map_value } => {
234 let entries = map_value
237 .iter()
238 .map(|entry| {
239 format!("{} -> {}", entry.key.to_string(), entry.value.to_string())
240 })
241 .collect::<Vec<_>>()
242 .join(", ");
243 format!("Map{{{{{}}}}}", entries)
244 },
245 StackItem::InteropInterface { id, interface } => {
246 format!("InteropInterface{{id={}, interface={}}}", id, interface)
247 },
248 }
249 }
250
251 pub fn as_bytes(&self) -> Option<Vec<u8>> {
253 match self {
254 StackItem::ByteString { value } | StackItem::Buffer { value } =>
255 {
257 Some(
258 base64::decode(value.trim_end())
259 .expect(&format!("Failed to decode the string: {}", value)),
260 )
261 },
262 StackItem::Integer { value } => {
264 let mut bytes = value.to_be_bytes().to_vec();
265 bytes.reverse();
266 Some(bytes)
267 },
268 _ => None,
269 }
270 }
271
272 pub fn as_array(&self) -> Option<Vec<StackItem>> {
274 match self {
275 StackItem::Array { value } | StackItem::Struct { value } => Some(value.clone()),
276 _ => None,
277 }
278 }
279
280 pub fn as_int(&self) -> Option<i64> {
282 match self {
283 StackItem::Integer { value } => Some(*value),
284 StackItem::Boolean { value } => Some(if *value { 1 } else { 0 }),
285 StackItem::Pointer { value } => Some(*value),
286 _ => None,
287 }
288 }
289
290 pub fn as_map(&self) -> Option<HashMap<StackItem, StackItem>> {
292 match self {
293 StackItem::Map { value } => {
294 let mut map = HashMap::new();
295 for entry in value {
296 map.insert(entry.key.clone(), entry.value.clone());
297 }
298 Some(map)
299 },
300 _ => None,
301 }
302 }
303
304 pub fn as_address(&self) -> Option<Address> {
306 self.as_bytes().and_then(|mut bytes| {
307 bytes.reverse();
308 Some(H160::from_slice(&bytes).to_address())
309 })
310 }
311
312 pub fn as_public_key(&self) -> Option<Secp256r1PublicKey> {
314 self.as_bytes().and_then(|bytes| Secp256r1PublicKey::from_bytes(&bytes).ok())
315 }
316
317 pub fn as_hash160(&self) -> Option<H160> {
319 self.as_bytes().and_then(|bytes| Some(H160::from_slice(&bytes)))
320 }
321
322 pub fn as_hash256(&self) -> Option<H256> {
324 self.as_bytes().and_then(|bytes| Some(H256::from_slice(&bytes)))
325 }
326
327 pub fn as_interop(&self, interface_name: &str) -> Option<StackItem> {
328 match self {
329 StackItem::Integer { value } => Some(StackItem::InteropInterface {
330 id: value.to_string(),
331 interface: interface_name.to_string(),
332 }),
333 StackItem::Boolean { value } => Some(StackItem::InteropInterface {
334 id: value.to_string(),
335 interface: interface_name.to_string(),
336 }),
337 StackItem::ByteString { value } => Some(StackItem::InteropInterface {
338 id: value.to_string(),
339 interface: interface_name.to_string(),
340 }),
341 StackItem::Buffer { value } => Some(StackItem::InteropInterface {
342 id: value.to_string(),
343 interface: interface_name.to_string(),
344 }),
345 _ => None,
346 }
347 }
348
349 pub fn len(&self) -> Option<usize> {
350 match self {
351 StackItem::Array { value } | StackItem::Struct { value } => Some(value.len()),
352 _ => None,
353 }
354 }
355
356 pub fn is_empty(&self) -> Option<bool> {
357 self.len().map(|len| len == 0)
358 }
359
360 pub fn get(&self, index: usize) -> Option<StackItem> {
361 self.as_array().and_then(|arr| arr.get(index).cloned())
362 }
363
364 pub fn get_iterator_id(&self) -> Option<&String> {
365 if let StackItem::InteropInterface { id, .. } = self {
366 Some(id)
367 } else {
368 None
369 }
370 }
371
372 pub fn get_interface_name(&self) -> Option<&String> {
373 if let StackItem::InteropInterface { interface, .. } = self {
374 Some(interface)
375 } else {
376 None
377 }
378 }
379}
380
381impl From<String> for StackItem {
382 fn from(value: String) -> Self {
383 StackItem::ByteString { value }
384 }
385}
386
387impl From<H160> for StackItem {
388 fn from(value: H160) -> Self {
389 StackItem::ByteString { value: ToString::to_string(&value) }
390 }
391}
392
393impl From<u8> for StackItem {
394 fn from(value: u8) -> Self {
395 StackItem::Integer { value: value as i64 }
396 }
397}
398
399impl From<i8> for StackItem {
400 fn from(value: i8) -> Self {
401 StackItem::Integer { value: value as i64 }
402 }
403}
404
405impl From<u16> for StackItem {
406 fn from(value: u16) -> Self {
407 StackItem::Integer { value: value as i64 }
408 }
409}
410
411impl From<i16> for StackItem {
412 fn from(value: i16) -> Self {
413 StackItem::Integer { value: value as i64 }
414 }
415}
416
417impl From<u32> for StackItem {
418 fn from(value: u32) -> Self {
419 StackItem::Integer { value: value as i64 }
420 }
421}
422
423impl From<i32> for StackItem {
424 fn from(value: i32) -> Self {
425 StackItem::Integer { value: value as i64 }
426 }
427}
428
429impl From<u64> for StackItem {
430 fn from(value: u64) -> Self {
431 StackItem::Integer { value: value as i64 }
432 }
433}
434impl From<&str> for StackItem {
435 fn from(value: &str) -> Self {
436 StackItem::ByteString { value: value.to_string() }
437 }
438}