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