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 StackItem::Integer { value } => Some(value.to_string()),
207 StackItem::Boolean { value } => Some(value.to_string()),
208 _ => None,
209 }
210 }
211
212 pub fn to_string(&self) -> String {
214 match self {
215 StackItem::Any => "Any".to_string(),
216 StackItem::Pointer { value: pointer } => format!("Pointer{{value={}}}", pointer),
217 StackItem::Boolean { value: boolean } => format!("Boolean{{value={}}}", boolean),
218 StackItem::Integer { value: integer } => format!("Integer{{value={}}}", integer),
219 StackItem::ByteString { value: byteString } =>
220 format!("ByteString{{value={:?}}}", byteString),
221 StackItem::Buffer { value: buffer } => format!("Buffer{{value={:?}}}", buffer),
222 StackItem::Array { value: array } => {
223 let values = array.iter().map(StackItem::to_string).collect::<Vec<_>>().join(", ");
224 format!("Array{{value=[{}]}}", values)
225 },
226 StackItem::Struct { value: _struct } => {
227 let values =
228 _struct.iter().map(StackItem::to_string).collect::<Vec<_>>().join(", ");
229 format!("Struct{{value=[{}]}}", values)
230 },
231 StackItem::Map { value: map_value } => {
232 let entries = map_value
235 .iter()
236 .map(|entry| {
237 format!("{} -> {}", entry.key.to_string(), entry.value.to_string())
238 })
239 .collect::<Vec<_>>()
240 .join(", ");
241 format!("Map{{{{{}}}}}", entries)
242 },
243 StackItem::InteropInterface { id, interface } => {
244 format!("InteropInterface{{id={}, interface={}}}", id, interface)
245 },
246 }
247 }
248
249 pub fn as_bytes(&self) -> Option<Vec<u8>> {
251 match self {
252 StackItem::ByteString { value } | StackItem::Buffer { value } =>
253 Some(
255 base64::decode(value.trim_end())
256 .expect(&format!("Failed to decode the string: {}", value)),
257 ),
258 StackItem::Integer { value } => {
260 let mut bytes = value.to_be_bytes().to_vec();
261 bytes.reverse();
262 Some(bytes)
263 },
264 _ => None,
265 }
266 }
267
268 pub fn as_array(&self) -> Option<Vec<StackItem>> {
270 match self {
271 StackItem::Array { value } | StackItem::Struct { value } => Some(value.clone()),
272 _ => None,
273 }
274 }
275
276 pub fn as_int(&self) -> Option<i64> {
278 match self {
279 StackItem::Integer { value } => Some(*value),
280 StackItem::Boolean { value } => Some(if *value { 1 } else { 0 }),
281 StackItem::Pointer { value } => Some(*value),
282 _ => None,
283 }
284 }
285
286 pub fn as_map(&self) -> Option<HashMap<StackItem, StackItem>> {
288 match self {
289 StackItem::Map { value } => {
290 let mut map = HashMap::new();
291 for entry in value {
292 map.insert(entry.key.clone(), entry.value.clone());
293 }
294 Some(map)
295 },
296 _ => None,
297 }
298 }
299
300 pub fn as_address(&self) -> Option<Address> {
302 self.as_bytes().and_then(|mut bytes| {
303 bytes.reverse();
304 Some(H160::from_slice(&bytes).to_address())
305 })
306 }
307
308 pub fn as_public_key(&self) -> Option<Secp256r1PublicKey> {
310 self.as_bytes().and_then(|bytes| Secp256r1PublicKey::from_bytes(&bytes).ok())
311 }
312
313 pub fn as_hash160(&self) -> Option<H160> {
315 self.as_bytes().and_then(|bytes| Some(H160::from_slice(&bytes)))
316 }
317
318 pub fn as_hash256(&self) -> Option<H256> {
320 self.as_bytes().and_then(|bytes| Some(H256::from_slice(&bytes)))
321 }
322
323 pub fn as_interop(&self, interface_name: &str) -> Option<StackItem> {
324 match self {
325 StackItem::Integer { value } => Some(StackItem::InteropInterface {
326 id: value.to_string(),
327 interface: interface_name.to_string(),
328 }),
329 StackItem::Boolean { value } => Some(StackItem::InteropInterface {
330 id: value.to_string(),
331 interface: interface_name.to_string(),
332 }),
333 StackItem::ByteString { value } => Some(StackItem::InteropInterface {
334 id: value.to_string(),
335 interface: interface_name.to_string(),
336 }),
337 StackItem::Buffer { value } => Some(StackItem::InteropInterface {
338 id: value.to_string(),
339 interface: interface_name.to_string(),
340 }),
341 _ => None,
342 }
343 }
344
345 pub fn len(&self) -> Option<usize> {
346 match self {
347 StackItem::Array { value } | StackItem::Struct { value } => Some(value.len()),
348 _ => None,
349 }
350 }
351
352 pub fn is_empty(&self) -> Option<bool> {
353 self.len().map(|len| len == 0)
354 }
355
356 pub fn get(&self, index: usize) -> Option<StackItem> {
357 self.as_array().and_then(|arr| arr.get(index).cloned())
358 }
359
360 pub fn get_iterator_id(&self) -> Option<&String> {
361 if let StackItem::InteropInterface { id, .. } = self {
362 Some(id)
363 } else {
364 None
365 }
366 }
367
368 pub fn get_interface_name(&self) -> Option<&String> {
369 if let StackItem::InteropInterface { interface, .. } = self {
370 Some(interface)
371 } else {
372 None
373 }
374 }
375}
376
377impl From<String> for StackItem {
378 fn from(value: String) -> Self {
379 StackItem::ByteString { value }
380 }
381}
382
383impl From<H160> for StackItem {
384 fn from(value: H160) -> Self {
385 StackItem::ByteString { value: ToString::to_string(&value) }
386 }
387}
388
389impl From<u8> for StackItem {
390 fn from(value: u8) -> Self {
391 StackItem::Integer { value: value as i64 }
392 }
393}
394
395impl From<i8> for StackItem {
396 fn from(value: i8) -> Self {
397 StackItem::Integer { value: value as i64 }
398 }
399}
400
401impl From<u16> for StackItem {
402 fn from(value: u16) -> Self {
403 StackItem::Integer { value: value as i64 }
404 }
405}
406
407impl From<i16> for StackItem {
408 fn from(value: i16) -> Self {
409 StackItem::Integer { value: value as i64 }
410 }
411}
412
413impl From<u32> for StackItem {
414 fn from(value: u32) -> Self {
415 StackItem::Integer { value: value as i64 }
416 }
417}
418
419impl From<i32> for StackItem {
420 fn from(value: i32) -> Self {
421 StackItem::Integer { value: value as i64 }
422 }
423}
424
425impl From<u64> for StackItem {
426 fn from(value: u64) -> Self {
427 StackItem::Integer { value: value as i64 }
428 }
429}
430impl From<&str> for StackItem {
431 fn from(value: &str) -> Self {
432 StackItem::ByteString { value: value.to_string() }
433 }
434}