1#![deny(missing_docs)]
3
4mod cancun;
5mod shanghai;
6
7pub use cancun::Cancun;
8pub use shanghai::ShangHai;
9
10#[macro_export]
12macro_rules! opcodes {
13 ($name:ident, $desc:literal) => {
14 #[doc = $desc]
15 $name
16 };
17 {
18 $version:ident,
19 $((
20 $opcode:expr,
21 $name:ident,
22 $gas:expr,
23 $input:expr,
24 $output:expr,
25 $desc:literal,
26 $since:ident,
27 $group:ident
28 )),+
29 } => {
30 #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
32 pub enum $version {
33 #[cfg(feature = "data")]
34 Data(u8),
36 $(
37 #[doc = concat!(" ", $desc)]
38 $name,
39 )*
40 }
41
42 impl From<u8> for $version {
43 fn from(value: u8) -> Self {
44 match value {
45 $(
46 $opcode => Self::$name,
47 )*
48 _ => unreachable!("Invalid opcode."),
49 }
50 }
51 }
52
53 impl From<$version> for u8 {
54 fn from(version: $version) -> Self {
55 match version {
56 #[cfg(feature = "data")]
57 $version::Data(data) => data,
58 $(
59 $version::$name => $opcode,
60 )*
61 }
62 }
63 }
64
65 impl OpCode for $version {
66 fn group(&self) -> Group {
67 match self {
68 #[cfg(feature = "data")]
69 Self::Data(_) => Group::StopArithmetic,
70 $(
71 Self::$name => Group::$group,
72 )*
73 }
74 }
75
76 fn gas(&self) -> u16 {
77 match self {
78 #[cfg(feature = "data")]
79 Self::Data(_) => 0,
80 $(
81 Self::$name => $gas,
82 )*
83 }
84 }
85
86 fn since(&self) -> Upgrade {
87 match self {
88 #[cfg(feature = "data")]
89 Self::Data(_) => Upgrade::Shanghai,
90 $(
91 Self::$name => Upgrade::$since,
92 )*
93 }
94 }
95
96 fn stack_in(&self) -> u16 {
97 match self {
98 #[cfg(feature = "data")]
99 Self::Data(_) => 0,
100 $(
101 Self::$name => $input,
102 )*
103 }
104 }
105
106 fn stack_out(&self) -> u16 {
107 match self {
108 #[cfg(feature = "data")]
109 Self::Data(_) => 0,
110 $(
111 Self::$name => $output,
112 )*
113 }
114 }
115 }
116
117 impl core::str::FromStr for $version {
118 type Err = ();
119
120 fn from_str(s: &str) -> Result<Self, Self::Err> {
121 paste::paste! {
122 match s {
123 $(
124 stringify!([< $name:lower >]) => Ok(Self::$name),
125 )*
126 _ => Err(()),
127 }
128 }
129 }
130 }
131
132 paste::paste! {
133 #[doc = concat!(" For each ", stringify!($version), " operator.")]
134 #[macro_export]
135 macro_rules! [<for_each_ $version:lower _operator>] {
136 ($mac:ident) => {
137 $mac! {
138 $([<_ $name:lower>] => $name),+
139 }
140 }
141 }
142 }
143 };
144}
145
146#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
148pub enum Group {
149 StopArithmetic,
151 ComparisonBitwiseLogic,
153 Sha3,
155 EnvironmentalInformation,
157 BlockInformation,
159 StackMemoryStorageFlow,
161 Push,
163 Duplication,
165 Exchange,
167 Logging,
169 System,
171}
172
173#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
175pub enum Upgrade {
176 Frontier,
178 Byzantium,
180 Constantinople,
182 Istanbul,
184 Berlin,
186 London,
188 Shanghai,
190 Cancun,
192}
193
194pub trait OpCode: From<u8> + Into<u8> {
196 fn stack_in(&self) -> u16;
198
199 fn stack_out(&self) -> u16;
201
202 fn since(&self) -> Upgrade;
204
205 fn group(&self) -> Group;
207
208 fn gas(&self) -> u16;
210}