1use crate::opcodes;
2use crate::types::Type;
3use std::sync::atomic::{AtomicUsize, Ordering};
4
5#[derive(Debug, Clone)]
6pub struct InsnNode {
7 pub opcode: u8,
8}
9
10impl From<u8> for InsnNode {
11 fn from(value: u8) -> Self {
12 Self { opcode: value }
13 }
14}
15
16#[derive(Debug, Clone)]
17pub struct IntInsnNode {
18 pub insn: InsnNode,
19 pub operand: i32,
20}
21
22#[derive(Debug, Clone)]
23pub struct VarInsnNode {
24 pub insn: InsnNode,
25 pub var_index: u16,
26}
27
28#[derive(Debug, Clone)]
29pub struct TypeInsnNode {
30 pub insn: InsnNode,
31 pub type_index: u16,
32}
33
34#[derive(Debug, Clone)]
35pub struct FieldInsnNode {
36 pub insn: InsnNode,
37 pub field_ref: MemberRef,
38}
39
40#[derive(Debug, Clone)]
41pub struct MethodInsnNode {
42 pub insn: InsnNode,
43 pub method_ref: MemberRef,
44}
45
46#[derive(Debug, Clone)]
47pub struct InvokeInterfaceInsnNode {
48 pub insn: InsnNode,
49 pub method_index: u16,
50 pub count: u8,
51}
52
53#[derive(Debug, Clone)]
54pub struct InvokeDynamicInsnNode {
55 pub insn: InsnNode,
56 pub method_index: u16,
57 pub name: Option<String>,
58 pub descriptor: Option<String>,
59 pub bootstrap_method: Option<Handle>,
60 pub bootstrap_args: Vec<BootstrapArgument>,
61}
62
63#[derive(Debug, Clone)]
64pub struct JumpInsnNode {
65 pub insn: InsnNode,
66 pub offset: i32,
67}
68
69#[derive(Debug, Clone)]
70pub struct JumpLabelInsnNode {
71 pub insn: InsnNode,
72 pub target: LabelNode,
73}
74
75#[derive(Debug, Clone)]
76pub struct LdcInsnNode {
77 pub insn: InsnNode,
78 pub value: LdcValue,
79}
80
81#[derive(Debug, Clone)]
82pub struct IincInsnNode {
83 pub insn: InsnNode,
84 pub var_index: u16,
85 pub increment: i16,
86}
87
88#[derive(Debug, Clone)]
89pub struct TableSwitchInsnNode {
90 pub insn: InsnNode,
91 pub default_offset: i32,
92 pub low: i32,
93 pub high: i32,
94 pub offsets: Vec<i32>,
95}
96
97#[derive(Debug, Clone)]
98pub struct LookupSwitchInsnNode {
99 pub insn: InsnNode,
100 pub default_offset: i32,
101 pub pairs: Vec<(i32, i32)>,
102}
103
104#[derive(Debug, Clone)]
105pub struct TableSwitchLabelInsnNode {
106 pub insn: InsnNode,
107 pub default_target: LabelNode,
108 pub low: i32,
109 pub high: i32,
110 pub targets: Vec<LabelNode>,
111}
112
113#[derive(Debug, Clone)]
114pub struct LookupSwitchLabelInsnNode {
115 pub insn: InsnNode,
116 pub default_target: LabelNode,
117 pub pairs: Vec<(i32, LabelNode)>,
118}
119
120#[derive(Debug, Clone)]
121pub struct MultiANewArrayInsnNode {
122 pub insn: InsnNode,
123 pub type_index: u16,
124 pub dimensions: u8,
125}
126
127static NEXT_LABEL_ID: AtomicUsize = AtomicUsize::new(0);
128
129fn next_label_id() -> usize {
130 NEXT_LABEL_ID.fetch_add(1, Ordering::Relaxed)
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
134pub struct Label {
135 pub id: usize,
136}
137
138impl Default for Label {
139 fn default() -> Self {
140 Self::new()
141 }
142}
143
144impl Label {
145 pub fn new() -> Self {
146 Self {
147 id: next_label_id(),
148 }
149 }
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
153pub struct LabelNode {
154 pub id: usize,
155}
156
157impl Default for LabelNode {
158 fn default() -> Self {
159 Self::new()
160 }
161}
162
163impl LabelNode {
164 pub fn new() -> Self {
165 Self {
166 id: next_label_id(),
167 }
168 }
169
170 pub fn from_label(label: Label) -> Self {
171 Self { id: label.id }
172 }
173}
174
175#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
176pub struct LineNumberInsnNode {
177 pub line: u16,
178 pub start: LabelNode,
179}
180impl LineNumberInsnNode {
181 pub(crate) fn new(line: u16, start: LabelNode) -> Self {
182 Self { line, start }
183 }
184}
185
186#[derive(Debug, Clone)]
187pub struct TryCatchBlockNode {
188 pub start: LabelNode,
189 pub end: LabelNode,
190 pub handler: LabelNode,
191 pub catch_type: Option<String>,
192}
193
194#[derive(Debug, Clone)]
195pub enum AbstractInsnNode {
196 Label(LabelNode),
197 LineNumber(LineNumberInsnNode),
198 Insn(Insn),
199 JumpLabel(JumpLabelInsnNode),
200 TableSwitchLabel(TableSwitchLabelInsnNode),
201 LookupSwitchLabel(LookupSwitchLabelInsnNode),
202}
203
204#[derive(Debug, Clone)]
205pub enum Insn {
206 Simple(InsnNode),
207 Int(IntInsnNode),
208 Var(VarInsnNode),
209 Type(TypeInsnNode),
210 Field(FieldInsnNode),
211 Method(MethodInsnNode),
212 InvokeInterface(InvokeInterfaceInsnNode),
213 InvokeDynamic(InvokeDynamicInsnNode),
214 Jump(JumpInsnNode),
215 Ldc(LdcInsnNode),
216 Iinc(IincInsnNode),
217 TableSwitch(TableSwitchInsnNode),
218 LookupSwitch(LookupSwitchInsnNode),
219 MultiANewArray(MultiANewArrayInsnNode),
220}
221
222#[derive(Debug, Clone)]
223pub enum MemberRef {
224 Index(u16),
225 Symbolic {
226 owner: String,
227 name: String,
228 descriptor: String,
229 },
230}
231
232#[derive(Debug, Clone)]
233pub enum LdcValue {
234 Index(u16),
235 String(String),
236 Type(Type),
237 Int(i32),
238 Float(f32),
239 Long(i64),
240 Double(f64),
241}
242
243#[derive(Debug, Clone)]
244pub struct Handle {
245 pub reference_kind: u8,
246 pub owner: String,
247 pub name: String,
248 pub descriptor: String,
249 pub is_interface: bool,
250}
251
252#[derive(Debug, Clone)]
253pub enum BootstrapArgument {
254 Integer(i32),
255 Float(f32),
256 Long(i64),
257 Double(f64),
258 String(String),
259 Class(String),
260 MethodType(String),
261 Handle(Handle),
262}
263
264#[derive(Debug, Clone, Default)]
265pub struct InsnList {
266 insns: Vec<Insn>,
267}
268
269impl InsnList {
270 pub fn new() -> Self {
271 Self { insns: Vec::new() }
272 }
273
274 pub fn add<T: Into<Insn>>(&mut self, insn: T) -> &mut Self {
275 self.insns.push(insn.into());
276 self
277 }
278
279 pub fn insns(&self) -> &[Insn] {
280 &self.insns
281 }
282
283 pub fn into_insns(self) -> Vec<Insn> {
284 self.insns
285 }
286}
287
288#[derive(Debug, Clone, Default)]
289pub struct NodeList {
290 nodes: Vec<AbstractInsnNode>,
291}
292
293impl NodeList {
294 pub fn new() -> Self {
295 Self { nodes: Vec::new() }
296 }
297
298 pub fn add<T: Into<AbstractInsnNode>>(&mut self, node: T) -> &mut Self {
299 self.nodes.push(node.into());
300 self
301 }
302
303 pub fn add_node(&mut self, node: AbstractInsnNode) -> &mut Self {
304 self.nodes.push(node);
305 self
306 }
307
308 pub fn nodes(&self) -> &[AbstractInsnNode] {
309 &self.nodes
310 }
311
312 pub fn into_nodes(self) -> Vec<AbstractInsnNode> {
313 self.nodes
314 }
315}
316
317impl From<LabelNode> for AbstractInsnNode {
318 fn from(value: LabelNode) -> Self {
319 AbstractInsnNode::Label(value)
320 }
321}
322
323impl From<LineNumberInsnNode> for AbstractInsnNode {
324 fn from(value: LineNumberInsnNode) -> Self {
325 AbstractInsnNode::LineNumber(value)
326 }
327}
328
329impl From<Insn> for AbstractInsnNode {
330 fn from(value: Insn) -> Self {
331 AbstractInsnNode::Insn(value)
332 }
333}
334
335impl From<JumpLabelInsnNode> for AbstractInsnNode {
336 fn from(value: JumpLabelInsnNode) -> Self {
337 AbstractInsnNode::JumpLabel(value)
338 }
339}
340
341impl From<TableSwitchLabelInsnNode> for AbstractInsnNode {
342 fn from(value: TableSwitchLabelInsnNode) -> Self {
343 AbstractInsnNode::TableSwitchLabel(value)
344 }
345}
346
347impl From<LookupSwitchLabelInsnNode> for AbstractInsnNode {
348 fn from(value: LookupSwitchLabelInsnNode) -> Self {
349 AbstractInsnNode::LookupSwitchLabel(value)
350 }
351}
352
353impl FieldInsnNode {
354 pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
355 Self {
356 insn: opcode.into(),
357 field_ref: MemberRef::Symbolic {
358 owner: owner.to_string(),
359 name: name.to_string(),
360 descriptor: descriptor.to_string(),
361 },
362 }
363 }
364
365 pub fn from_index(opcode: u8, index: u16) -> Self {
366 Self {
367 insn: opcode.into(),
368 field_ref: MemberRef::Index(index),
369 }
370 }
371}
372
373impl MethodInsnNode {
374 pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
375 Self {
376 insn: opcode.into(),
377 method_ref: MemberRef::Symbolic {
378 owner: owner.to_string(),
379 name: name.to_string(),
380 descriptor: descriptor.to_string(),
381 },
382 }
383 }
384
385 pub fn from_index(opcode: u8, index: u16) -> Self {
386 Self {
387 insn: opcode.into(),
388 method_ref: MemberRef::Index(index),
389 }
390 }
391}
392
393impl InvokeDynamicInsnNode {
394 pub fn new(
395 name: &str,
396 descriptor: &str,
397 bootstrap_method: Handle,
398 bootstrap_args: &[BootstrapArgument],
399 ) -> Self {
400 Self {
401 insn: opcodes::INVOKEDYNAMIC.into(),
402 method_index: 0,
403 name: Some(name.to_string()),
404 descriptor: Some(descriptor.to_string()),
405 bootstrap_method: Some(bootstrap_method),
406 bootstrap_args: bootstrap_args.to_vec(),
407 }
408 }
409
410 pub fn from_index(index: u16) -> Self {
411 Self {
412 insn: opcodes::INVOKEDYNAMIC.into(),
413 method_index: index,
414 name: None,
415 descriptor: None,
416 bootstrap_method: None,
417 bootstrap_args: Vec::new(),
418 }
419 }
420}
421
422impl LdcInsnNode {
423 pub fn from_index(opcode: u8, index: u16) -> Self {
424 Self {
425 insn: opcode.into(),
426 value: LdcValue::Index(index),
427 }
428 }
429
430 pub fn int(value: i32) -> Self {
431 Self {
432 insn: opcodes::LDC.into(),
433 value: LdcValue::Int(value),
434 }
435 }
436
437 pub fn long(value: i64) -> Self {
438 Self {
439 insn: opcodes::LDC2_W.into(),
440 value: LdcValue::Long(value),
441 }
442 }
443
444 pub fn float(value: f32) -> Self {
445 Self {
446 insn: opcodes::LDC.into(),
447 value: LdcValue::Float(value),
448 }
449 }
450
451 pub fn double(value: f64) -> Self {
452 Self {
453 insn: opcodes::LDC2_W.into(),
454 value: LdcValue::Double(value),
455 }
456 }
457
458 pub fn short(value: i16) -> Self {
459 Self::int(value as i32)
460 }
461
462 pub fn char(value: u16) -> Self {
463 Self::int(value as i32)
464 }
465
466 pub fn byte(value: i8) -> Self {
467 Self::int(value as i32)
468 }
469
470 pub fn boolean(value: bool) -> Self {
471 Self::int(if value { 1 } else { 0 })
472 }
473
474 pub fn string(value: &str) -> Self {
475 Self {
476 insn: opcodes::LDC.into(),
477 value: LdcValue::String(value.to_string()),
478 }
479 }
480
481 pub fn typed(value: Type) -> Self {
482 Self {
483 insn: opcodes::LDC.into(),
484 value: LdcValue::Type(value),
485 }
486 }
487}
488
489impl From<InsnNode> for Insn {
490 fn from(value: InsnNode) -> Self {
491 Insn::Simple(value)
492 }
493}
494
495impl From<IntInsnNode> for Insn {
496 fn from(value: IntInsnNode) -> Self {
497 Insn::Int(value)
498 }
499}
500
501impl From<VarInsnNode> for Insn {
502 fn from(value: VarInsnNode) -> Self {
503 Insn::Var(value)
504 }
505}
506
507impl From<TypeInsnNode> for Insn {
508 fn from(value: TypeInsnNode) -> Self {
509 Insn::Type(value)
510 }
511}
512
513impl From<FieldInsnNode> for Insn {
514 fn from(value: FieldInsnNode) -> Self {
515 Insn::Field(value)
516 }
517}
518
519impl From<MethodInsnNode> for Insn {
520 fn from(value: MethodInsnNode) -> Self {
521 Insn::Method(value)
522 }
523}
524
525impl From<InvokeInterfaceInsnNode> for Insn {
526 fn from(value: InvokeInterfaceInsnNode) -> Self {
527 Insn::InvokeInterface(value)
528 }
529}
530
531impl From<InvokeDynamicInsnNode> for Insn {
532 fn from(value: InvokeDynamicInsnNode) -> Self {
533 Insn::InvokeDynamic(value)
534 }
535}
536
537impl From<JumpInsnNode> for Insn {
538 fn from(value: JumpInsnNode) -> Self {
539 Insn::Jump(value)
540 }
541}
542
543impl From<LdcInsnNode> for Insn {
544 fn from(value: LdcInsnNode) -> Self {
545 Insn::Ldc(value)
546 }
547}
548
549impl From<IincInsnNode> for Insn {
550 fn from(value: IincInsnNode) -> Self {
551 Insn::Iinc(value)
552 }
553}
554
555impl From<TableSwitchInsnNode> for Insn {
556 fn from(value: TableSwitchInsnNode) -> Self {
557 Insn::TableSwitch(value)
558 }
559}
560
561impl From<LookupSwitchInsnNode> for Insn {
562 fn from(value: LookupSwitchInsnNode) -> Self {
563 Insn::LookupSwitch(value)
564 }
565}
566
567impl From<MultiANewArrayInsnNode> for Insn {
568 fn from(value: MultiANewArrayInsnNode) -> Self {
569 Insn::MultiANewArray(value)
570 }
571}