1use crate::opcodes;
2use std::sync::atomic::{AtomicUsize, Ordering};
3
4#[derive(Debug, Clone)]
5pub struct InsnNode {
6 pub opcode: u8,
7}
8
9impl From<u8> for InsnNode {
10 fn from(value: u8) -> Self {
11 Self { opcode: value }
12 }
13}
14
15#[derive(Debug, Clone)]
16pub struct IntInsnNode {
17 pub insn: InsnNode,
18 pub operand: i32,
19}
20
21#[derive(Debug, Clone)]
22pub struct VarInsnNode {
23 pub insn: InsnNode,
24 pub var_index: u16,
25}
26
27#[derive(Debug, Clone)]
28pub struct TypeInsnNode {
29 pub insn: InsnNode,
30 pub type_index: u16,
31}
32
33#[derive(Debug, Clone)]
34pub struct FieldInsnNode {
35 pub insn: InsnNode,
36 pub field_ref: MemberRef,
37}
38
39#[derive(Debug, Clone)]
40pub struct MethodInsnNode {
41 pub insn: InsnNode,
42 pub method_ref: MemberRef,
43}
44
45#[derive(Debug, Clone)]
46pub struct InvokeInterfaceInsnNode {
47 pub insn: InsnNode,
48 pub method_index: u16,
49 pub count: u8,
50}
51
52#[derive(Debug, Clone)]
53pub struct InvokeDynamicInsnNode {
54 pub insn: InsnNode,
55 pub method_index: u16,
56}
57
58#[derive(Debug, Clone)]
59pub struct JumpInsnNode {
60 pub insn: InsnNode,
61 pub offset: i32,
62}
63
64#[derive(Debug, Clone)]
65pub struct JumpLabelInsnNode {
66 pub insn: InsnNode,
67 pub target: LabelNode,
68}
69
70#[derive(Debug, Clone)]
71pub struct LdcInsnNode {
72 pub insn: InsnNode,
73 pub value: LdcValue,
74}
75
76#[derive(Debug, Clone)]
77pub struct IincInsnNode {
78 pub insn: InsnNode,
79 pub var_index: u16,
80 pub increment: i16,
81}
82
83#[derive(Debug, Clone)]
84pub struct TableSwitchInsnNode {
85 pub insn: InsnNode,
86 pub default_offset: i32,
87 pub low: i32,
88 pub high: i32,
89 pub offsets: Vec<i32>,
90}
91
92#[derive(Debug, Clone)]
93pub struct LookupSwitchInsnNode {
94 pub insn: InsnNode,
95 pub default_offset: i32,
96 pub pairs: Vec<(i32, i32)>,
97}
98
99#[derive(Debug, Clone)]
100pub struct MultiANewArrayInsnNode {
101 pub insn: InsnNode,
102 pub type_index: u16,
103 pub dimensions: u8,
104}
105
106static NEXT_LABEL_ID: AtomicUsize = AtomicUsize::new(0);
107
108fn next_label_id() -> usize {
109 NEXT_LABEL_ID.fetch_add(1, Ordering::Relaxed)
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
113pub struct Label {
114 pub id: usize,
115}
116
117impl Label {
118 pub fn new() -> Self {
119 Self { id: next_label_id() }
120 }
121}
122
123#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
124pub struct LabelNode {
125 pub id: usize,
126}
127
128impl LabelNode {
129 pub fn new() -> Self {
130 Self { id: next_label_id() }
131 }
132
133 pub fn from_label(label: Label) -> Self {
134 Self { id: label.id }
135 }
136}
137
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
139pub struct LineNumberInsnNode {
140 pub line: u16,
141 pub start: LabelNode,
142}
143impl LineNumberInsnNode{
144 pub(crate) fn new(line: u16, start: LabelNode) -> Self {
145 Self { line, start }
146 }
147}
148
149#[derive(Debug, Clone)]
150pub struct TryCatchBlockNode {
151 pub start: LabelNode,
152 pub end: LabelNode,
153 pub handler: LabelNode,
154 pub catch_type: Option<String>,
155}
156
157#[derive(Debug, Clone)]
158pub enum AbstractInsnNode {
159 Label(LabelNode),
160 LineNumber(LineNumberInsnNode),
161 Insn(Insn),
162 JumpLabel(JumpLabelInsnNode),
163}
164
165#[derive(Debug, Clone)]
166pub enum Insn {
167 Simple(InsnNode),
168 Int(IntInsnNode),
169 Var(VarInsnNode),
170 Type(TypeInsnNode),
171 Field(FieldInsnNode),
172 Method(MethodInsnNode),
173 InvokeInterface(InvokeInterfaceInsnNode),
174 InvokeDynamic(InvokeDynamicInsnNode),
175 Jump(JumpInsnNode),
176 Ldc(LdcInsnNode),
177 Iinc(IincInsnNode),
178 TableSwitch(TableSwitchInsnNode),
179 LookupSwitch(LookupSwitchInsnNode),
180 MultiANewArray(MultiANewArrayInsnNode),
181}
182
183#[derive(Debug, Clone)]
184pub enum MemberRef {
185 Index(u16),
186 Symbolic {
187 owner: String,
188 name: String,
189 descriptor: String,
190 },
191}
192
193#[derive(Debug, Clone)]
194pub enum LdcValue {
195 Index(u16),
196 String(String),
197}
198
199#[derive(Debug, Clone, Default)]
200pub struct InsnList {
201 insns: Vec<Insn>,
202}
203
204impl InsnList {
205 pub fn new() -> Self {
206 Self { insns: Vec::new() }
207 }
208
209 pub fn add<T: Into<Insn>>(&mut self, insn: T) -> &mut Self {
210 self.insns.push(insn.into());
211 self
212 }
213
214 pub fn insns(&self) -> &[Insn] {
215 &self.insns
216 }
217
218 pub fn into_insns(self) -> Vec<Insn> {
219 self.insns
220 }
221}
222
223
224
225#[derive(Debug, Clone, Default)]
226pub struct NodeList {
227 nodes: Vec<AbstractInsnNode>,
228}
229
230impl NodeList {
231 pub fn new() -> Self {
232 Self { nodes: Vec::new() }
233 }
234
235 pub fn add<T: Into<AbstractInsnNode>>(&mut self, node: T) -> &mut Self {
236 self.nodes.push(node.into());
237 self
238 }
239
240 pub fn nodes(&self) -> &[AbstractInsnNode] {
241 &self.nodes
242 }
243
244 pub fn into_nodes(self) -> Vec<AbstractInsnNode> {
245 self.nodes
246 }
247}
248
249impl From<LabelNode> for AbstractInsnNode {
250 fn from(value: LabelNode) -> Self {
251 AbstractInsnNode::Label(value)
252 }
253}
254
255impl From<LineNumberInsnNode> for AbstractInsnNode {
256 fn from(value: LineNumberInsnNode) -> Self {
257 AbstractInsnNode::LineNumber(value)
258 }
259}
260
261impl From<Insn> for AbstractInsnNode {
262 fn from(value: Insn) -> Self {
263 AbstractInsnNode::Insn(value)
264 }
265}
266
267impl From<JumpLabelInsnNode> for AbstractInsnNode {
268 fn from(value: JumpLabelInsnNode) -> Self {
269 AbstractInsnNode::JumpLabel(value)
270 }
271}
272
273impl FieldInsnNode {
274 pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
275 Self {
276 insn: opcode.into(),
277 field_ref: MemberRef::Symbolic {
278 owner: owner.to_string(),
279 name: name.to_string(),
280 descriptor: descriptor.to_string(),
281 },
282 }
283 }
284
285 pub fn from_index(opcode: u8, index: u16) -> Self {
286 Self {
287 insn: opcode.into(),
288 field_ref: MemberRef::Index(index),
289 }
290 }
291}
292
293impl MethodInsnNode {
294 pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
295 Self {
296 insn: opcode.into(),
297 method_ref: MemberRef::Symbolic {
298 owner: owner.to_string(),
299 name: name.to_string(),
300 descriptor: descriptor.to_string(),
301 },
302 }
303 }
304
305 pub fn from_index(opcode: u8, index: u16) -> Self {
306 Self {
307 insn: opcode.into(),
308 method_ref: MemberRef::Index(index),
309 }
310 }
311}
312
313impl LdcInsnNode {
314 pub fn from_index(opcode: u8, index: u16) -> Self {
315 Self {
316 insn: opcode.into(),
317 value: LdcValue::Index(index),
318 }
319 }
320
321 pub fn string(value: &str) -> Self {
322 Self {
323 insn: opcodes::LDC.into(),
324 value: LdcValue::String(value.to_string()),
325 }
326 }
327}
328
329impl From<InsnNode> for Insn {
330 fn from(value: InsnNode) -> Self {
331 Insn::Simple(value)
332 }
333}
334
335impl From<IntInsnNode> for Insn {
336 fn from(value: IntInsnNode) -> Self {
337 Insn::Int(value)
338 }
339}
340
341impl From<VarInsnNode> for Insn {
342 fn from(value: VarInsnNode) -> Self {
343 Insn::Var(value)
344 }
345}
346
347impl From<TypeInsnNode> for Insn {
348 fn from(value: TypeInsnNode) -> Self {
349 Insn::Type(value)
350 }
351}
352
353impl From<FieldInsnNode> for Insn {
354 fn from(value: FieldInsnNode) -> Self {
355 Insn::Field(value)
356 }
357}
358
359impl From<MethodInsnNode> for Insn {
360 fn from(value: MethodInsnNode) -> Self {
361 Insn::Method(value)
362 }
363}
364
365impl From<InvokeInterfaceInsnNode> for Insn {
366 fn from(value: InvokeInterfaceInsnNode) -> Self {
367 Insn::InvokeInterface(value)
368 }
369}
370
371impl From<InvokeDynamicInsnNode> for Insn {
372 fn from(value: InvokeDynamicInsnNode) -> Self {
373 Insn::InvokeDynamic(value)
374 }
375}
376
377impl From<JumpInsnNode> for Insn {
378 fn from(value: JumpInsnNode) -> Self {
379 Insn::Jump(value)
380 }
381}
382
383impl From<LdcInsnNode> for Insn {
384 fn from(value: LdcInsnNode) -> Self {
385 Insn::Ldc(value)
386 }
387}
388
389impl From<IincInsnNode> for Insn {
390 fn from(value: IincInsnNode) -> Self {
391 Insn::Iinc(value)
392 }
393}
394
395impl From<TableSwitchInsnNode> for Insn {
396 fn from(value: TableSwitchInsnNode) -> Self {
397 Insn::TableSwitch(value)
398 }
399}
400
401impl From<LookupSwitchInsnNode> for Insn {
402 fn from(value: LookupSwitchInsnNode) -> Self {
403 Insn::LookupSwitch(value)
404 }
405}
406
407impl From<MultiANewArrayInsnNode> for Insn {
408 fn from(value: MultiANewArrayInsnNode) -> Self {
409 Insn::MultiANewArray(value)
410 }
411}