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