1use getset::Getters;
3use num_enum::TryFromPrimitive;
4use strum_macros::{Display, EnumCount, EnumString};
5
6#[derive(
7 Display, EnumString, EnumCount, TryFromPrimitive, Debug, Copy, Clone, PartialEq, Eq, Hash,
8)]
9#[repr(u8)]
10pub enum OpCode {
11 #[strum(serialize = "PushInt8")]
12 PushInt8 = 0x00,
13 #[strum(serialize = "PushInt16")]
14 PushInt16 = 0x01,
15 #[strum(serialize = "PushInt32")]
16 PushInt32 = 0x02,
17 #[strum(serialize = "PushInt64")]
18 PushInt64 = 0x03,
19 #[strum(serialize = "PushInt128")]
20 PushInt128 = 0x04,
21 #[strum(serialize = "PushInt256")]
22 PushInt256 = 0x05,
23 #[strum(serialize = "PushTrue")]
24 PushTrue = 0x08,
25 #[strum(serialize = "PushFalse")]
26 PushFalse = 0x09,
27 #[strum(serialize = "PushA")]
28 PushA = 0x0A,
29 #[strum(serialize = "PushNull")]
30 PushNull = 0x0B,
31 #[strum(serialize = "PushData1")]
32 PushData1 = 0x0C,
33 #[strum(serialize = "PushData2")]
34 PushData2 = 0x0D,
35 #[strum(serialize = "PushData4")]
36 PushData4 = 0x0E,
37 #[strum(serialize = "PushM1")]
38 PushM1 = 0x0F,
39 #[strum(serialize = "Push0")]
40 Push0 = 0x10,
41 #[strum(serialize = "Push1")]
42 Push1 = 0x11,
43 #[strum(serialize = "Push2")]
44 Push2 = 0x12,
45 #[strum(serialize = "Push3")]
46 Push3 = 0x13,
47 #[strum(serialize = "Push4")]
48 Push4 = 0x14,
49 #[strum(serialize = "Push5")]
50 Push5 = 0x15,
51 #[strum(serialize = "Push6")]
52 Push6 = 0x16,
53 #[strum(serialize = "Push7")]
54 Push7 = 0x17,
55 #[strum(serialize = "Push8")]
56 Push8 = 0x18,
57 #[strum(serialize = "Push9")]
58 Push9 = 0x19,
59 #[strum(serialize = "Push10")]
60 Push10 = 0x1A,
61 #[strum(serialize = "Push11")]
62 Push11 = 0x1B,
63 #[strum(serialize = "Push12")]
64 Push12 = 0x1C,
65 #[strum(serialize = "Push13")]
66 Push13 = 0x1D,
67 #[strum(serialize = "Push14")]
68 Push14 = 0x1E,
69 #[strum(serialize = "Push15")]
70 Push15 = 0x1F,
71 #[strum(serialize = "Push16")]
72 Push16 = 0x20,
73
74 #[strum(serialize = "Nop")]
75 Nop = 0x21,
76 #[strum(serialize = "Jmp")]
77 Jmp = 0x22,
78 #[strum(serialize = "JmpL")]
79 JmpL = 0x23,
80 #[strum(serialize = "JmpIf")]
81 JmpIf = 0x24,
82 #[strum(serialize = "JmpIfL")]
83 JmpIfL = 0x25,
84 #[strum(serialize = "JmpIfNot")]
85 JmpIfNot = 0x26,
86 #[strum(serialize = "JmpIfNotL")]
87 JmpIfNotL = 0x27,
88 #[strum(serialize = "JmpEq")]
89 JmpEq = 0x28,
90 #[strum(serialize = "JmpEqL")]
91 JmpEqL = 0x29,
92 #[strum(serialize = "JmpNe")]
93 JmpNe = 0x2A,
94 #[strum(serialize = "JmpNeL")]
95 JmpNeL = 0x2B,
96 #[strum(serialize = "JmpGt")]
97 JmpGt = 0x2C,
98 #[strum(serialize = "JmpGtL")]
99 JmpGtL = 0x2D,
100 #[strum(serialize = "JmpGe")]
101 JmpGe = 0x2E,
102 #[strum(serialize = "JmpGeL")]
103 JmpGeL = 0x2F,
104 #[strum(serialize = "JmpLt")]
105 JmpLt = 0x30,
106 #[strum(serialize = "JmpLtL")]
107 JmpLtL = 0x31,
108 #[strum(serialize = "JmpLe")]
109 JmpLe = 0x32,
110 #[strum(serialize = "JmpLeL")]
111 JmpLeL = 0x33,
112 #[strum(serialize = "Call")]
113 Call = 0x34,
114 #[strum(serialize = "CallL")]
115 CallL = 0x35,
116 #[strum(serialize = "CallA")]
117 CallA = 0x36,
118 #[strum(serialize = "CallT")]
119 CallT = 0x37,
120 #[strum(serialize = "Abort")]
121 Abort = 0x38,
122 #[strum(serialize = "Assert")]
123 Assert = 0x39,
124 #[strum(serialize = "Throw")]
125 Throw = 0x3A,
126 #[strum(serialize = "Try")]
127 Try = 0x3B,
128 #[strum(serialize = "TryL")]
129 TryL = 0x3C,
130 #[strum(serialize = "EndTry")]
131 EndTry = 0x3D,
132 #[strum(serialize = "EndTryL")]
133 EndTryL = 0x3E,
134 #[strum(serialize = "EndFinally")]
135 EndFinally = 0x3F,
136 #[strum(serialize = "Ret")]
137 Ret = 0x40,
138 #[strum(serialize = "Syscall")]
139 Syscall = 0x41,
140
141 #[strum(serialize = "Depth")]
142 Depth = 0x43,
143 #[strum(serialize = "Drop")]
144 Drop = 0x45,
145 #[strum(serialize = "Nip")]
146 Nip = 0x46,
147 #[strum(serialize = "Xdrop")]
148 Xdrop = 0x48,
149 #[strum(serialize = "Clear")]
150 Clear = 0x49,
151 #[strum(serialize = "Dup")]
152 Dup = 0x4A,
153 #[strum(serialize = "Over")]
154 Over = 0x4B,
155 #[strum(serialize = "Pick")]
156 Pick = 0x4D,
157 #[strum(serialize = "Tuck")]
158 Tuck = 0x4E,
159 #[strum(serialize = "Swap")]
160 Swap = 0x50,
161 #[strum(serialize = "Rot")]
162 Rot = 0x51,
163 #[strum(serialize = "Roll")]
164 Roll = 0x52,
165 #[strum(serialize = "Reverse3")]
166 Reverse3 = 0x53,
167 #[strum(serialize = "Reverse4")]
168 Reverse4 = 0x54,
169 #[strum(serialize = "Reverse5")]
170 ReverseN = 0x55,
171
172 #[strum(serialize = "InitSSlot")]
173 InitSSLot = 0x56,
174 #[strum(serialize = "InitSlot")]
175 InitSlot = 0x57,
176
177 #[strum(serialize = "LdSFLd0")]
178 LdSFLd0 = 0x58,
179 #[strum(serialize = "LdSFLd1")]
180 LdSFLd1 = 0x59,
181 #[strum(serialize = "LdSFLd2")]
182 LdSFLd2 = 0x5A,
183 #[strum(serialize = "LdSFLd3")]
184 LdSFLd3 = 0x5B,
185 #[strum(serialize = "LdSFLd4")]
186 LdSFLd4 = 0x5C,
187 #[strum(serialize = "LdSFLd5")]
188 LdSFLd5 = 0x5D,
189 #[strum(serialize = "LdSFLd6")]
190 LdSFLd6 = 0x5E,
191 #[strum(serialize = "LdSFLd")]
192 LdSFLd = 0x5F,
193
194 #[strum(serialize = "StSFLd0")]
195 StSFLd0 = 0x60,
196 #[strum(serialize = "StSFLd1")]
197 StSFLd1 = 0x61,
198 #[strum(serialize = "StSFLd2")]
199 StSFLd2 = 0x62,
200 #[strum(serialize = "StSFLd3")]
201 StSFLd3 = 0x63,
202 #[strum(serialize = "StSFLd4")]
203 StSFLd4 = 0x64,
204 #[strum(serialize = "StSFLd5")]
205 StSFLd5 = 0x65,
206 #[strum(serialize = "StSFLd6")]
207 StSFLd6 = 0x66,
208 #[strum(serialize = "StSFLd")]
209 StSFLd = 0x67,
210
211 #[strum(serialize = "LdLoc0")]
212 LdLoc0 = 0x68,
213 #[strum(serialize = "LdLoc1")]
214 LdLoc1 = 0x69,
215 #[strum(serialize = "LdLoc2")]
216 LdLoc2 = 0x6A,
217 #[strum(serialize = "LdLoc3")]
218 LdLoc3 = 0x6B,
219 #[strum(serialize = "LdLoc4")]
220 LdLoc4 = 0x6C,
221 #[strum(serialize = "LdLoc5")]
222 LdLoc5 = 0x6D,
223 #[strum(serialize = "LdLoc6")]
224 LdLoc6 = 0x6E,
225 #[strum(serialize = "LdLoc")]
226 LdLoc = 0x6F,
227
228 #[strum(serialize = "StLoc0")]
229 StLoc0 = 0x70,
230 #[strum(serialize = "StLoc1")]
231 StLoc1 = 0x71,
232 #[strum(serialize = "StLoc2")]
233 StLoc2 = 0x72,
234 #[strum(serialize = "StLoc3")]
235 StLoc3 = 0x73,
236 #[strum(serialize = "StLoc4")]
237 StLoc4 = 0x74,
238 #[strum(serialize = "StLoc5")]
239 StLoc5 = 0x75,
240 #[strum(serialize = "StLoc6")]
241 StLoc6 = 0x76,
242 #[strum(serialize = "StLoc")]
243 StLoc = 0x77,
244
245 #[strum(serialize = "LdArg0")]
246 LdArg0 = 0x78,
247 #[strum(serialize = "LdArg1")]
248 LdArg1 = 0x79,
249 #[strum(serialize = "LdArg2")]
250 LdArg2 = 0x7A,
251 #[strum(serialize = "LdArg3")]
252 LdArg3 = 0x7B,
253 #[strum(serialize = "LdArg4")]
254 LdArg4 = 0x7C,
255 #[strum(serialize = "LdArg5")]
256 LdArg5 = 0x7D,
257 #[strum(serialize = "LdArg6")]
258 LdArg6 = 0x7E,
259 #[strum(serialize = "LdArg")]
260 LdArg = 0x7F,
261
262 #[strum(serialize = "StArg0")]
263 StArg0 = 0x80,
264 #[strum(serialize = "StArg1")]
265 StArg1 = 0x81,
266 #[strum(serialize = "StArg2")]
267 StArg2 = 0x82,
268 #[strum(serialize = "StArg3")]
269 StArg3 = 0x83,
270 #[strum(serialize = "StArg4")]
271 StArg4 = 0x84,
272 #[strum(serialize = "StArg5")]
273 StArg5 = 0x85,
274 #[strum(serialize = "StArg6")]
275 StArg6 = 0x86,
276 #[strum(serialize = "StArg")]
277 StArg = 0x87,
278
279 #[strum(serialize = "NewBuffer")]
280 NewBuffer = 0x88,
281 #[strum(serialize = "MemCpy")]
282 MemCpy = 0x89,
283 #[strum(serialize = "Cat")]
284 Cat = 0x8B,
285 #[strum(serialize = "Substr")]
286 Substr = 0x8C,
287 #[strum(serialize = "Left")]
288 Left = 0x8D,
289 #[strum(serialize = "Right")]
290 Right = 0x8E,
291
292 #[strum(serialize = "Invert")]
293 Invert = 0x90,
294 #[strum(serialize = "And")]
295 And = 0x91,
296 #[strum(serialize = "Or")]
297 Or = 0x92,
298 #[strum(serialize = "Xor")]
299 Xor = 0x93,
300 #[strum(serialize = "Equal")]
301 Equal = 0x97,
302 #[strum(serialize = "NotEqual")]
303 NotEqual = 0x98,
304
305 #[strum(serialize = "Sign")]
306 Sign = 0x99,
307 #[strum(serialize = "Abs")]
308 Abs = 0x9A,
309 #[strum(serialize = "Negate")]
310 Negate = 0x9B,
311 #[strum(serialize = "Inc")]
312 Inc = 0x9C,
313 #[strum(serialize = "Dec")]
314 Dec = 0x9D,
315 #[strum(serialize = "Add")]
316 Add = 0x9E,
317 #[strum(serialize = "Sub")]
318 Sub = 0x9F,
319 #[strum(serialize = "Mul")]
320 Mul = 0xA0,
321 #[strum(serialize = "Div")]
322 Div = 0xA1,
323 #[strum(serialize = "Mod")]
324 Mod = 0xA2,
325 #[strum(serialize = "Pow")]
326 Pow = 0xA3,
327 #[strum(serialize = "Sqrt")]
328 Sqrt = 0xA4,
329 #[strum(serialize = "ModMul")]
330 ModMul = 0xA5,
331 #[strum(serialize = "ModPow")]
332 ModPow = 0xA6,
333 #[strum(serialize = "Shl")]
334 Shl = 0xA8,
335 #[strum(serialize = "Shr")]
336 Shr = 0xA9,
337 #[strum(serialize = "Not")]
338 Not = 0xAA,
339 #[strum(serialize = "BoolAnd")]
340 BoolAnd = 0xAB,
341 #[strum(serialize = "BoolOr")]
342 BoolOr = 0xAC,
343 #[strum(serialize = "Nz")]
344 Nz = 0xB1,
345 #[strum(serialize = "NumEqual")]
346 NumEqual = 0xB3,
347 #[strum(serialize = "NumNotEqual")]
348 NumNotEqual = 0xB4,
349 #[strum(serialize = "Lt")]
350 Lt = 0xB5,
351 #[strum(serialize = "Le")]
352 Le = 0xB6,
353 #[strum(serialize = "Gt")]
354 Gt = 0xB7,
355 #[strum(serialize = "Ge")]
356 Ge = 0xB8,
357 #[strum(serialize = "Min")]
358 Min = 0xB9,
359 #[strum(serialize = "Max")]
360 Max = 0xBA,
361 #[strum(serialize = "Within")]
362 Within = 0xBB,
363
364 #[strum(serialize = "PackMap")]
365 PackMap = 0xBE,
366 #[strum(serialize = "PackStruct")]
367 PackStruct = 0xBF,
368 #[strum(serialize = "Pack")]
369 Pack = 0xC0,
370 #[strum(serialize = "Unpack")]
371 Unpack = 0xC1,
372 #[strum(serialize = "NewArray0")]
373 NewArray0 = 0xC2,
374 #[strum(serialize = "NewArray")]
375 NewArray = 0xC3,
376 #[strum(serialize = "NewArrayT")]
377 NewArrayT = 0xC4,
378 #[strum(serialize = "NewStruct0")]
379 NewStruct0 = 0xC5,
380 #[strum(serialize = "NewStruct")]
381 NewStruct = 0xC6,
382 #[strum(serialize = "NewMap")]
383 NewMap = 0xC8,
384 #[strum(serialize = "Size")]
385 Size = 0xCA,
386 #[strum(serialize = "HasKey")]
387 HasKey = 0xCB,
388 #[strum(serialize = "Keys")]
389 Keys = 0xCC,
390 #[strum(serialize = "Values")]
391 Values = 0xCD,
392 #[strum(serialize = "PickItem")]
393 PickItem = 0xCE,
394 #[strum(serialize = "Append")]
395 Append = 0xCF,
396 #[strum(serialize = "SetItem")]
397 SetItem = 0xD0,
398 #[strum(serialize = "ReverseItems")]
399 ReverseItems = 0xD1,
400 #[strum(serialize = "Remove")]
401 Remove = 0xD2,
402 #[strum(serialize = "ClearItems")]
403 ClearItems = 0xD3,
404 #[strum(serialize = "PopItem")]
405 PopItem = 0xD4,
406
407 #[strum(serialize = "IsNull")]
408 IsNull = 0xD8,
409 #[strum(serialize = "IsType")]
410 IsType = 0xD9,
411 #[strum(serialize = "Convert")]
412 Convert = 0xDB,
413
414 #[strum(serialize = "AbortMsg")]
415 AbortMsg = 0xE0,
416 #[strum(serialize = "AssertMsg")]
417 AssertMsg = 0xE1,
418}
419
420impl OpCode {
421 pub fn price(self) -> u32 {
422 match self {
423 OpCode::PushInt8
424 | OpCode::PushInt16
425 | OpCode::PushInt32
426 | OpCode::PushInt64
427 | OpCode::PushNull
428 | OpCode::PushM1
429 | OpCode::Push0
430 | OpCode::Push1
431 | OpCode::Push2
432 | OpCode::Push3
433 | OpCode::Push4
434 | OpCode::Push5
435 | OpCode::Push6
436 | OpCode::Push7
437 | OpCode::Push8
438 | OpCode::Push9
439 | OpCode::Push10
440 | OpCode::Push11
441 | OpCode::Push12
442 | OpCode::Push13
443 | OpCode::Push14
444 | OpCode::Push15
445 | OpCode::Push16
446 | OpCode::Nop
447 | OpCode::Assert => 1,
448 OpCode::PushInt128
449 | OpCode::PushInt256
450 | OpCode::PushA
451 | OpCode::Try
452 | OpCode::Sign
453 | OpCode::Abs
454 | OpCode::Negate
455 | OpCode::Inc
456 | OpCode::Dec
457 | OpCode::Not
458 | OpCode::Nz
459 | OpCode::Size => 1 << 2,
460 OpCode::PushData1
461 | OpCode::And
462 | OpCode::Or
463 | OpCode::Xor
464 | OpCode::Add
465 | OpCode::Sub
466 | OpCode::Mul
467 | OpCode::Div
468 | OpCode::Mod
469 | OpCode::Shl
470 | OpCode::Shr
471 | OpCode::BoolAnd
472 | OpCode::BoolOr
473 | OpCode::NumEqual
474 | OpCode::NumNotEqual
475 | OpCode::Lt
476 | OpCode::Le
477 | OpCode::Gt
478 | OpCode::Ge
479 | OpCode::Min
480 | OpCode::Max
481 | OpCode::Within
482 | OpCode::NewMap => 1 << 3,
483 OpCode::Xdrop
484 | OpCode::Clear
485 | OpCode::Roll
486 | OpCode::ReverseN
487 | OpCode::InitSSLot
488 | OpCode::NewArray0
489 | OpCode::NewStruct0
490 | OpCode::Keys
491 | OpCode::Remove
492 | OpCode::ClearItems => 1 << 4,
493 OpCode::Equal | OpCode::NotEqual | OpCode::ModMul => 1 << 5,
494 OpCode::InitSlot | OpCode::Pow | OpCode::HasKey | OpCode::PickItem => 1 << 6,
495 OpCode::NewBuffer => 1 << 8,
496 OpCode::PushData2
497 | OpCode::Call
498 | OpCode::CallL
499 | OpCode::CallA
500 | OpCode::Throw
501 | OpCode::NewArray
502 | OpCode::NewArrayT
503 | OpCode::NewStruct => 1 << 9,
504 OpCode::MemCpy
505 | OpCode::Cat
506 | OpCode::Substr
507 | OpCode::Left
508 | OpCode::Right
509 | OpCode::Sqrt
510 | OpCode::ModPow
511 | OpCode::PackMap
512 | OpCode::PackStruct
513 | OpCode::Pack
514 | OpCode::Unpack => 1 << 11,
515 OpCode::PushData4 => 1 << 12,
516 OpCode::Values
517 | OpCode::Append
518 | OpCode::SetItem
519 | OpCode::ReverseItems
520 | OpCode::Convert => 1 << 13,
521 OpCode::CallT => 1 << 15,
522 OpCode::Abort | OpCode::Ret | OpCode::Syscall => 0,
523 _ => 1 << 1,
524 }
525 }
526 pub fn opcode(self) -> u8 {
527 self as u8
528 }
529
530 pub fn to_hex_string(self) -> String {
531 format!("{:02X}", self as u8)
532 }
533
534 pub fn operand_size(self) -> Option<OperandSize> {
535 match self {
536 Self::PushInt8
537 | Self::Jmp
538 | Self::JmpIf
539 | Self::JmpIfNot
540 | Self::JmpEq
541 | Self::JmpNe
542 | Self::JmpGt
543 | Self::JmpGe
544 | Self::JmpLt
545 | Self::JmpLe
546 | Self::Call
547 | Self::EndTry
548 | Self::InitSSLot
549 | Self::LdSFLd
550 | Self::StSFLd
551 | Self::LdLoc
552 | Self::StLoc
553 | Self::LdArg
554 | Self::StArg
555 | Self::NewArrayT
556 | Self::IsType
557 | Self::Convert => Some(OperandSize::with_size(1)),
558
559 Self::PushInt16 | Self::CallT | Self::Try | Self::InitSlot =>
560 Some(OperandSize::with_size(2)),
561
562 Self::PushInt32
563 | Self::PushA
564 | Self::JmpL
565 | Self::JmpIfL
566 | Self::JmpIfNotL
567 | Self::JmpEqL
568 | Self::JmpNeL
569 | Self::JmpGtL
570 | Self::JmpGeL
571 | Self::JmpLtL
572 | Self::JmpLeL
573 | Self::CallL
574 | Self::EndTryL
575 | Self::Syscall => Some(OperandSize::with_size(4)),
576
577 Self::PushInt64 | Self::TryL => Some(OperandSize::with_size(8)),
578
579 Self::PushInt128 => Some(OperandSize::with_size(16)),
580
581 Self::PushInt256 => Some(OperandSize::with_size(32)),
582
583 Self::PushData1 => Some(OperandSize::with_prefix_size(1)),
584 Self::PushData2 => Some(OperandSize::with_prefix_size(2)),
585 Self::PushData4 => Some(OperandSize::with_prefix_size(4)),
586
587 _ => None,
588 }
589 }
590}
591
592#[derive(Clone, Debug, Getters)]
604pub struct OperandSize {
605 #[get = "pub"]
606 prefix_size: u8,
607 #[get = "pub"]
608 size: u8,
609}
610
611impl OperandSize {
612 pub fn with_size(size: u8) -> Self {
613 Self { prefix_size: 0, size }
614 }
615
616 pub fn with_prefix_size(prefix_size: u8) -> Self {
617 Self { prefix_size, size: 0 }
618 }
619}