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 Default for Label {
118 fn default() -> Self {
119 Self::new()
120 }
121}
122
123impl Label {
124 pub fn new() -> Self {
125 Self {
126 id: next_label_id(),
127 }
128 }
129}
130
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
132pub struct LabelNode {
133 pub id: usize,
134}
135
136impl Default for LabelNode {
137 fn default() -> Self {
138 Self::new()
139 }
140}
141
142impl LabelNode {
143 pub fn new() -> Self {
144 Self {
145 id: next_label_id(),
146 }
147 }
148
149 pub fn from_label(label: Label) -> Self {
150 Self { id: label.id }
151 }
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
155pub struct LineNumberInsnNode {
156 pub line: u16,
157 pub start: LabelNode,
158}
159impl LineNumberInsnNode {
160 pub(crate) fn new(line: u16, start: LabelNode) -> Self {
161 Self { line, start }
162 }
163}
164
165#[derive(Debug, Clone)]
166pub struct TryCatchBlockNode {
167 pub start: LabelNode,
168 pub end: LabelNode,
169 pub handler: LabelNode,
170 pub catch_type: Option<String>,
171}
172
173#[derive(Debug, Clone)]
174pub enum AbstractInsnNode {
175 Label(LabelNode),
176 LineNumber(LineNumberInsnNode),
177 Insn(Insn),
178 JumpLabel(JumpLabelInsnNode),
179}
180
181#[derive(Debug, Clone)]
182pub enum Insn {
183 Simple(InsnNode),
184 Int(IntInsnNode),
185 Var(VarInsnNode),
186 Type(TypeInsnNode),
187 Field(FieldInsnNode),
188 Method(MethodInsnNode),
189 InvokeInterface(InvokeInterfaceInsnNode),
190 InvokeDynamic(InvokeDynamicInsnNode),
191 Jump(JumpInsnNode),
192 Ldc(LdcInsnNode),
193 Iinc(IincInsnNode),
194 TableSwitch(TableSwitchInsnNode),
195 LookupSwitch(LookupSwitchInsnNode),
196 MultiANewArray(MultiANewArrayInsnNode),
197}
198
199#[derive(Debug, Clone)]
200pub enum MemberRef {
201 Index(u16),
202 Symbolic {
203 owner: String,
204 name: String,
205 descriptor: String,
206 },
207}
208
209#[derive(Debug, Clone)]
210pub enum LdcValue {
211 Index(u16),
212 String(String),
213 Int(i32),
214 Float(f32),
215 Long(i64),
216 Double(f64),
217}
218
219#[derive(Debug, Clone, Default)]
220pub struct InsnList {
221 insns: Vec<Insn>,
222}
223
224impl InsnList {
225 pub fn new() -> Self {
226 Self { insns: Vec::new() }
227 }
228
229 pub fn add<T: Into<Insn>>(&mut self, insn: T) -> &mut Self {
230 self.insns.push(insn.into());
231 self
232 }
233
234 pub fn insns(&self) -> &[Insn] {
235 &self.insns
236 }
237
238 pub fn into_insns(self) -> Vec<Insn> {
239 self.insns
240 }
241}
242
243#[derive(Debug, Clone, Default)]
244pub struct NodeList {
245 nodes: Vec<AbstractInsnNode>,
246}
247
248impl NodeList {
249 pub fn new() -> Self {
250 Self { nodes: Vec::new() }
251 }
252
253 pub fn add<T: Into<AbstractInsnNode>>(&mut self, node: T) -> &mut Self {
254 self.nodes.push(node.into());
255 self
256 }
257
258 pub fn nodes(&self) -> &[AbstractInsnNode] {
259 &self.nodes
260 }
261
262 pub fn into_nodes(self) -> Vec<AbstractInsnNode> {
263 self.nodes
264 }
265}
266
267impl From<LabelNode> for AbstractInsnNode {
268 fn from(value: LabelNode) -> Self {
269 AbstractInsnNode::Label(value)
270 }
271}
272
273impl From<LineNumberInsnNode> for AbstractInsnNode {
274 fn from(value: LineNumberInsnNode) -> Self {
275 AbstractInsnNode::LineNumber(value)
276 }
277}
278
279impl From<Insn> for AbstractInsnNode {
280 fn from(value: Insn) -> Self {
281 AbstractInsnNode::Insn(value)
282 }
283}
284
285impl From<JumpLabelInsnNode> for AbstractInsnNode {
286 fn from(value: JumpLabelInsnNode) -> Self {
287 AbstractInsnNode::JumpLabel(value)
288 }
289}
290
291impl FieldInsnNode {
292 pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
293 Self {
294 insn: opcode.into(),
295 field_ref: MemberRef::Symbolic {
296 owner: owner.to_string(),
297 name: name.to_string(),
298 descriptor: descriptor.to_string(),
299 },
300 }
301 }
302
303 pub fn from_index(opcode: u8, index: u16) -> Self {
304 Self {
305 insn: opcode.into(),
306 field_ref: MemberRef::Index(index),
307 }
308 }
309}
310
311impl MethodInsnNode {
312 pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
313 Self {
314 insn: opcode.into(),
315 method_ref: MemberRef::Symbolic {
316 owner: owner.to_string(),
317 name: name.to_string(),
318 descriptor: descriptor.to_string(),
319 },
320 }
321 }
322
323 pub fn from_index(opcode: u8, index: u16) -> Self {
324 Self {
325 insn: opcode.into(),
326 method_ref: MemberRef::Index(index),
327 }
328 }
329}
330
331impl LdcInsnNode {
332 pub fn from_index(opcode: u8, index: u16) -> Self {
333 Self {
334 insn: opcode.into(),
335 value: LdcValue::Index(index),
336 }
337 }
338
339 pub fn int(value: i32) -> Self {
340 Self {
341 insn: opcodes::LDC.into(),
342 value: LdcValue::Int(value),
343 }
344 }
345
346 pub fn long(value: i64) -> Self {
347 Self {
348 insn: opcodes::LDC2_W.into(),
349 value: LdcValue::Long(value),
350 }
351 }
352
353 pub fn float(value: f32) -> Self {
354 Self {
355 insn: opcodes::LDC.into(),
356 value: LdcValue::Float(value),
357 }
358 }
359
360 pub fn double(value: f64) -> Self {
361 Self {
362 insn: opcodes::LDC2_W.into(),
363 value: LdcValue::Double(value),
364 }
365 }
366
367 pub fn short(value: i16) -> Self {
368 Self::int(value as i32)
369 }
370
371 pub fn char(value: u16) -> Self {
372 Self::int(value as i32)
373 }
374
375 pub fn byte(value: i8) -> Self {
376 Self::int(value as i32)
377 }
378
379 pub fn boolean(value: bool) -> Self {
380 Self::int(if value { 1 } else { 0 })
381 }
382
383 pub fn string(value: &str) -> Self {
384 Self {
385 insn: opcodes::LDC.into(),
386 value: LdcValue::String(value.to_string()),
387 }
388 }
389}
390
391impl From<InsnNode> for Insn {
392 fn from(value: InsnNode) -> Self {
393 Insn::Simple(value)
394 }
395}
396
397impl From<IntInsnNode> for Insn {
398 fn from(value: IntInsnNode) -> Self {
399 Insn::Int(value)
400 }
401}
402
403impl From<VarInsnNode> for Insn {
404 fn from(value: VarInsnNode) -> Self {
405 Insn::Var(value)
406 }
407}
408
409impl From<TypeInsnNode> for Insn {
410 fn from(value: TypeInsnNode) -> Self {
411 Insn::Type(value)
412 }
413}
414
415impl From<FieldInsnNode> for Insn {
416 fn from(value: FieldInsnNode) -> Self {
417 Insn::Field(value)
418 }
419}
420
421impl From<MethodInsnNode> for Insn {
422 fn from(value: MethodInsnNode) -> Self {
423 Insn::Method(value)
424 }
425}
426
427impl From<InvokeInterfaceInsnNode> for Insn {
428 fn from(value: InvokeInterfaceInsnNode) -> Self {
429 Insn::InvokeInterface(value)
430 }
431}
432
433impl From<InvokeDynamicInsnNode> for Insn {
434 fn from(value: InvokeDynamicInsnNode) -> Self {
435 Insn::InvokeDynamic(value)
436 }
437}
438
439impl From<JumpInsnNode> for Insn {
440 fn from(value: JumpInsnNode) -> Self {
441 Insn::Jump(value)
442 }
443}
444
445impl From<LdcInsnNode> for Insn {
446 fn from(value: LdcInsnNode) -> Self {
447 Insn::Ldc(value)
448 }
449}
450
451impl From<IincInsnNode> for Insn {
452 fn from(value: IincInsnNode) -> Self {
453 Insn::Iinc(value)
454 }
455}
456
457impl From<TableSwitchInsnNode> for Insn {
458 fn from(value: TableSwitchInsnNode) -> Self {
459 Insn::TableSwitch(value)
460 }
461}
462
463impl From<LookupSwitchInsnNode> for Insn {
464 fn from(value: LookupSwitchInsnNode) -> Self {
465 Insn::LookupSwitch(value)
466 }
467}
468
469impl From<MultiANewArrayInsnNode> for Insn {
470 fn from(value: MultiANewArrayInsnNode) -> Self {
471 Insn::MultiANewArray(value)
472 }
473}