pulley_interpreter/
opcode.rs1macro_rules! define_opcode {
4 (
5 $(
6 $( #[$attr:meta] )*
7 $snake_name:ident = $name:ident $( {
8 $(
9 $( #[$field_attr:meta] )*
10 $field:ident : $field_ty:ty
11 ),*
12 } )? ;
13 )*
14 ) => {
15 #[repr(u8)]
17 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18 pub enum Opcode {
19 $(
20 $( #[$attr] )*
21 $name,
22 )*
23 ExtendedOp,
25 }
26
27 impl Opcode {
28 pub const MAX: u8 = Opcode::ExtendedOp as u8;
30 }
31 }
32}
33for_each_op!(define_opcode);
34
35impl Opcode {
36 pub fn new(byte: u8) -> Option<Self> {
40 if byte <= Self::MAX {
41 Some(unsafe { Self::unchecked_new(byte) })
42 } else {
43 None
44 }
45 }
46
47 pub unsafe fn unchecked_new(byte: u8) -> Self {
53 debug_assert!(byte <= Self::MAX);
54 core::mem::transmute(byte)
55 }
56}
57
58macro_rules! define_extended_opcode {
59 (
60 $(
61 $( #[$attr:meta] )*
62 $snake_name:ident = $name:ident $( { $( $field:ident : $field_ty:ty ),* } )? ;
63 )*
64 ) => {
65 #[repr(u16)]
67 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
68 pub enum ExtendedOpcode {
69 $(
70 $( #[$attr] )*
71 $name,
72 )*
73 }
74
75 impl ExtendedOpcode {
76 pub const MAX: u16 = $(
78 if true { 1 } else { ExtendedOpcode::$name as u16 } +
79 )* 0;
80 }
81 };
82}
83for_each_extended_op!(define_extended_opcode);
84
85impl ExtendedOpcode {
86 pub fn new(bytes: u16) -> Option<Self> {
90 if bytes <= Self::MAX {
91 Some(unsafe { Self::unchecked_new(bytes) })
92 } else {
93 None
94 }
95 }
96
97 pub unsafe fn unchecked_new(byte: u16) -> Self {
103 debug_assert!(byte <= Self::MAX);
104 core::mem::transmute(byte)
105 }
106}