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 Int(i32),
198 Float(f32),
199 Long(i64),
200 Double(f64),
201}
202
203#[derive(Debug, Clone, Default)]
204pub struct InsnList {
205 insns: Vec<Insn>,
206}
207
208impl InsnList {
209 pub fn new() -> Self {
210 Self { insns: Vec::new() }
211 }
212
213 pub fn add<T: Into<Insn>>(&mut self, insn: T) -> &mut Self {
214 self.insns.push(insn.into());
215 self
216 }
217
218 pub fn insns(&self) -> &[Insn] {
219 &self.insns
220 }
221
222 pub fn into_insns(self) -> Vec<Insn> {
223 self.insns
224 }
225}
226
227
228
229#[derive(Debug, Clone, Default)]
230pub struct NodeList {
231 nodes: Vec<AbstractInsnNode>,
232}
233
234impl NodeList {
235 pub fn new() -> Self {
236 Self { nodes: Vec::new() }
237 }
238
239 pub fn add<T: Into<AbstractInsnNode>>(&mut self, node: T) -> &mut Self {
240 self.nodes.push(node.into());
241 self
242 }
243
244 pub fn nodes(&self) -> &[AbstractInsnNode] {
245 &self.nodes
246 }
247
248 pub fn into_nodes(self) -> Vec<AbstractInsnNode> {
249 self.nodes
250 }
251}
252
253impl From<LabelNode> for AbstractInsnNode {
254 fn from(value: LabelNode) -> Self {
255 AbstractInsnNode::Label(value)
256 }
257}
258
259impl From<LineNumberInsnNode> for AbstractInsnNode {
260 fn from(value: LineNumberInsnNode) -> Self {
261 AbstractInsnNode::LineNumber(value)
262 }
263}
264
265impl From<Insn> for AbstractInsnNode {
266 fn from(value: Insn) -> Self {
267 AbstractInsnNode::Insn(value)
268 }
269}
270
271impl From<JumpLabelInsnNode> for AbstractInsnNode {
272 fn from(value: JumpLabelInsnNode) -> Self {
273 AbstractInsnNode::JumpLabel(value)
274 }
275}
276
277impl FieldInsnNode {
278 pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
279 Self {
280 insn: opcode.into(),
281 field_ref: MemberRef::Symbolic {
282 owner: owner.to_string(),
283 name: name.to_string(),
284 descriptor: descriptor.to_string(),
285 },
286 }
287 }
288
289 pub fn from_index(opcode: u8, index: u16) -> Self {
290 Self {
291 insn: opcode.into(),
292 field_ref: MemberRef::Index(index),
293 }
294 }
295}
296
297impl MethodInsnNode {
298 pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
299 Self {
300 insn: opcode.into(),
301 method_ref: MemberRef::Symbolic {
302 owner: owner.to_string(),
303 name: name.to_string(),
304 descriptor: descriptor.to_string(),
305 },
306 }
307 }
308
309 pub fn from_index(opcode: u8, index: u16) -> Self {
310 Self {
311 insn: opcode.into(),
312 method_ref: MemberRef::Index(index),
313 }
314 }
315}
316
317impl LdcInsnNode {
318 pub fn from_index(opcode: u8, index: u16) -> Self {
319 Self {
320 insn: opcode.into(),
321 value: LdcValue::Index(index),
322 }
323 }
324
325 pub fn int(value: i32) -> Self {
326 Self {
327 insn: opcodes::LDC.into(),
328 value: LdcValue::Int(value),
329 }
330 }
331
332 pub fn long(value: i64) -> Self {
333 Self {
334 insn: opcodes::LDC2_W.into(),
335 value: LdcValue::Long(value),
336 }
337 }
338
339 pub fn float(value: f32) -> Self {
340 Self {
341 insn: opcodes::LDC.into(),
342 value: LdcValue::Float(value),
343 }
344 }
345
346 pub fn double(value: f64) -> Self {
347 Self {
348 insn: opcodes::LDC2_W.into(),
349 value: LdcValue::Double(value),
350 }
351 }
352
353 pub fn short(value: i16) -> Self {
354 Self::int(value as i32)
355 }
356
357 pub fn char(value: u16) -> Self {
358 Self::int(value as i32)
359 }
360
361 pub fn byte(value: i8) -> Self {
362 Self::int(value as i32)
363 }
364
365 pub fn boolean(value: bool) -> Self {
366 Self::int(if value { 1 } else { 0 })
367 }
368
369 pub fn string(value: &str) -> Self {
370 Self {
371 insn: opcodes::LDC.into(),
372 value: LdcValue::String(value.to_string()),
373 }
374 }
375
376}
377
378impl From<InsnNode> for Insn {
379 fn from(value: InsnNode) -> Self {
380 Insn::Simple(value)
381 }
382}
383
384impl From<IntInsnNode> for Insn {
385 fn from(value: IntInsnNode) -> Self {
386 Insn::Int(value)
387 }
388}
389
390impl From<VarInsnNode> for Insn {
391 fn from(value: VarInsnNode) -> Self {
392 Insn::Var(value)
393 }
394}
395
396impl From<TypeInsnNode> for Insn {
397 fn from(value: TypeInsnNode) -> Self {
398 Insn::Type(value)
399 }
400}
401
402impl From<FieldInsnNode> for Insn {
403 fn from(value: FieldInsnNode) -> Self {
404 Insn::Field(value)
405 }
406}
407
408impl From<MethodInsnNode> for Insn {
409 fn from(value: MethodInsnNode) -> Self {
410 Insn::Method(value)
411 }
412}
413
414impl From<InvokeInterfaceInsnNode> for Insn {
415 fn from(value: InvokeInterfaceInsnNode) -> Self {
416 Insn::InvokeInterface(value)
417 }
418}
419
420impl From<InvokeDynamicInsnNode> for Insn {
421 fn from(value: InvokeDynamicInsnNode) -> Self {
422 Insn::InvokeDynamic(value)
423 }
424}
425
426impl From<JumpInsnNode> for Insn {
427 fn from(value: JumpInsnNode) -> Self {
428 Insn::Jump(value)
429 }
430}
431
432impl From<LdcInsnNode> for Insn {
433 fn from(value: LdcInsnNode) -> Self {
434 Insn::Ldc(value)
435 }
436}
437
438impl From<IincInsnNode> for Insn {
439 fn from(value: IincInsnNode) -> Self {
440 Insn::Iinc(value)
441 }
442}
443
444impl From<TableSwitchInsnNode> for Insn {
445 fn from(value: TableSwitchInsnNode) -> Self {
446 Insn::TableSwitch(value)
447 }
448}
449
450impl From<LookupSwitchInsnNode> for Insn {
451 fn from(value: LookupSwitchInsnNode) -> Self {
452 Insn::LookupSwitch(value)
453 }
454}
455
456impl From<MultiANewArrayInsnNode> for Insn {
457 fn from(value: MultiANewArrayInsnNode) -> Self {
458 Insn::MultiANewArray(value)
459 }
460}