1#![doc = include_str!("readme.md")]
7
8use gaia_types::{GaiaError, Result};
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11
12#[derive(Debug, Clone)]
14pub struct JvmProgram {
15 pub name: String,
17 pub access_flags: JvmAccessFlags,
19 pub super_class: Option<String>,
21 pub interfaces: Vec<String>,
23 pub fields: Vec<JvmField>,
25 pub methods: Vec<JvmMethod>,
27 pub attributes: Vec<JvmAttribute>,
29 pub constant_pool: JvmConstantPool,
31 pub version: JvmVersion,
33 pub source_file: Option<String>,
35}
36
37#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
39pub struct JvmVersion {
40 pub major: u16,
42 pub minor: u16,
44}
45
46#[derive(Debug, Clone)]
48pub struct JvmAccessFlags {
49 pub is_public: bool,
51 pub is_final: bool,
53 pub is_super: bool,
55 pub is_interface: bool,
57 pub is_abstract: bool,
59 pub is_synthetic: bool,
61 pub is_annotation: bool,
63 pub is_enum: bool,
65 pub is_static: bool,
67 pub is_private: bool,
69 pub is_protected: bool,
71 pub is_volatile: bool,
73 pub is_transient: bool,
75}
76
77impl JvmAccessFlags {
78 pub const PUBLIC: JvmAccessFlags = JvmAccessFlags {
80 is_public: true,
81 is_final: false,
82 is_super: false,
83 is_interface: false,
84 is_abstract: false,
85 is_synthetic: false,
86 is_annotation: false,
87 is_enum: false,
88 is_static: false,
89 is_private: false,
90 is_protected: false,
91 is_volatile: false,
92 is_transient: false,
93 };
94
95 pub const PRIVATE: JvmAccessFlags = JvmAccessFlags {
96 is_public: false,
97 is_final: false,
98 is_super: false,
99 is_interface: false,
100 is_abstract: false,
101 is_synthetic: false,
102 is_annotation: false,
103 is_enum: false,
104 is_static: false,
105 is_private: true,
106 is_protected: false,
107 is_volatile: false,
108 is_transient: false,
109 };
110
111 pub const PROTECTED: JvmAccessFlags = JvmAccessFlags {
112 is_public: false,
113 is_final: false,
114 is_super: false,
115 is_interface: false,
116 is_abstract: false,
117 is_synthetic: false,
118 is_annotation: false,
119 is_enum: false,
120 is_static: false,
121 is_private: false,
122 is_protected: true,
123 is_volatile: false,
124 is_transient: false,
125 };
126
127 pub const STATIC: JvmAccessFlags = JvmAccessFlags {
128 is_public: false,
129 is_final: false,
130 is_super: false,
131 is_interface: false,
132 is_abstract: false,
133 is_synthetic: false,
134 is_annotation: false,
135 is_enum: false,
136 is_static: true,
137 is_private: false,
138 is_protected: false,
139 is_volatile: false,
140 is_transient: false,
141 };
142
143 pub const FINAL: JvmAccessFlags = JvmAccessFlags {
144 is_public: false,
145 is_final: true,
146 is_super: false,
147 is_interface: false,
148 is_abstract: false,
149 is_synthetic: false,
150 is_annotation: false,
151 is_enum: false,
152 is_static: false,
153 is_private: false,
154 is_protected: false,
155 is_volatile: false,
156 is_transient: false,
157 };
158
159 pub const ABSTRACT: JvmAccessFlags = JvmAccessFlags {
160 is_public: false,
161 is_final: false,
162 is_super: false,
163 is_interface: false,
164 is_abstract: true,
165 is_synthetic: false,
166 is_annotation: false,
167 is_enum: false,
168 is_static: false,
169 is_private: false,
170 is_protected: false,
171 is_volatile: false,
172 is_transient: false,
173 };
174
175 pub const VOLATILE: JvmAccessFlags = JvmAccessFlags {
176 is_public: false,
177 is_final: false,
178 is_super: false,
179 is_interface: false,
180 is_abstract: false,
181 is_synthetic: false,
182 is_annotation: false,
183 is_enum: false,
184 is_static: false,
185 is_private: false,
186 is_protected: false,
187 is_volatile: true,
188 is_transient: false,
189 };
190
191 pub const TRANSIENT: JvmAccessFlags = JvmAccessFlags {
192 is_public: false,
193 is_final: false,
194 is_super: false,
195 is_interface: false,
196 is_abstract: false,
197 is_synthetic: false,
198 is_annotation: false,
199 is_enum: false,
200 is_static: false,
201 is_private: false,
202 is_protected: false,
203 is_volatile: false,
204 is_transient: true,
205 };
206}
207
208use std::ops::BitOrAssign;
209
210impl BitOrAssign for JvmAccessFlags {
211 fn bitor_assign(&mut self, rhs: Self) {
212 self.is_public |= rhs.is_public;
213 self.is_final |= rhs.is_final;
214 self.is_super |= rhs.is_super;
215 self.is_interface |= rhs.is_interface;
216 self.is_abstract |= rhs.is_abstract;
217 self.is_synthetic |= rhs.is_synthetic;
218 self.is_annotation |= rhs.is_annotation;
219 self.is_enum |= rhs.is_enum;
220 self.is_static |= rhs.is_static;
221 self.is_private |= rhs.is_private;
222 self.is_protected |= rhs.is_protected;
223 self.is_volatile |= rhs.is_volatile;
224 self.is_transient |= rhs.is_transient;
225 }
226}
227
228#[derive(Debug, Clone)]
230pub struct JvmConstantPool {
231 pub symbol_table: HashMap<String, u16>,
233 pub entries: Vec<JvmConstantPoolEntry>,
235}
236
237#[derive(Debug, Clone, PartialEq)]
239pub enum JvmConstantPoolEntry {
240 Nop,
241 Utf8 {
242 value: String,
243 },
244 Integer {
246 value: i32,
247 },
248 Float {
250 value: f32,
251 },
252 Long {
254 value: i64,
255 },
256 Double {
258 value: f64,
259 },
260 Class {
262 name: String,
263 },
264 String {
266 value: String,
267 },
268 Fieldref {
270 class_name: String,
271 name: String,
272 descriptor: String,
273 },
274 Methodref {
276 class_name: String,
277 name: String,
278 descriptor: String,
279 },
280 InterfaceMethodref {
282 class_name: String,
283 name: String,
284 descriptor: String,
285 },
286 NameAndType {
288 name: String,
289 descriptor: String,
290 },
291}
292
293#[derive(Debug, Clone)]
295pub struct JvmMethod {
296 pub name: String,
298 pub descriptor: String,
300 pub access_flags: JvmAccessFlags,
302 pub instructions: Vec<JvmInstruction>,
304 pub max_stack: u16,
306 pub max_locals: u16,
308 pub exception_table: Vec<JvmExceptionHandler>,
310 pub attributes: Vec<JvmAttribute>,
312}
313
314#[derive(Debug, Clone)]
316pub struct JvmField {
317 pub name: String,
319 pub descriptor: String,
321 pub access_flags: JvmAccessFlags,
323 pub constant_value: Option<JvmConstantPoolEntry>,
325 pub attributes: Vec<JvmAttribute>,
327}
328
329#[derive(Debug, Clone, PartialEq)]
331pub enum JvmInstruction {
332 Nop,
334 AconstNull,
335 IconstM1,
336 Iconst0,
337 Iconst1,
338 Iconst2,
339 Iconst3,
340 Iconst4,
341 Iconst5,
342 Lconst0,
343 Lconst1,
344 Fconst0,
345 Fconst1,
346 Fconst2,
347 Dconst0,
348 Dconst1,
349
350 Bipush { value: i8 },
352 Sipush { value: i16 },
353
354 Ldc { symbol: String },
356 LdcW { symbol: String },
357 Ldc2W { symbol: String },
358
359 Iload { index: u16 },
361 Lload { index: u16 },
362 Fload { index: u16 },
363 Dload { index: u16 },
364 Aload { index: u16 },
365 Iload0,
366 Iload1,
367 Iload2,
368 Iload3,
369 Lload0,
370 Lload1,
371 Lload2,
372 Lload3,
373 Fload0,
374 Fload1,
375 Fload2,
376 Fload3,
377 Dload0,
378 Dload1,
379 Dload2,
380 Dload3,
381 Aload0,
382 Aload1,
383 Aload2,
384 Aload3,
385
386 Istore { index: u16 },
388 Lstore { index: u16 },
389 Fstore { index: u16 },
390 Dstore { index: u16 },
391 Astore { index: u16 },
392 Istore0,
393 Istore1,
394 Istore2,
395 Istore3,
396 Lstore0,
397 Lstore1,
398 Lstore2,
399 Lstore3,
400 Fstore0,
401 Fstore1,
402 Fstore2,
403 Fstore3,
404 Dstore0,
405 Dstore1,
406 Dstore2,
407 Dstore3,
408 Astore0,
409 Astore1,
410 Astore2,
411 Astore3,
412
413 Pop,
415 Pop2,
416 Dup,
417 DupX1,
418 DupX2,
419 Dup2,
420 Dup2X1,
421 Dup2X2,
422 Swap,
423
424 Iadd,
426 Ladd,
427 Fadd,
428 Dadd,
429 Isub,
430 Lsub,
431 Fsub,
432 Dsub,
433 Imul,
434 Lmul,
435 Fmul,
436 Dmul,
437 Idiv,
438 Ldiv,
439 Fdiv,
440 Ddiv,
441 Irem,
442 Lrem,
443 Frem,
444 Drem,
445 Ineg,
446 Lneg,
447 Fneg,
448 Dneg,
449
450 Ishl,
452 Lshl,
453 Ishr,
454 Lshr,
455 Iushr,
456 Lushr,
457 Iand,
458 Land,
459 Ior,
460 Lor,
461 Ixor,
462 Lxor,
463
464 Lcmp,
466 Fcmpl,
467 Fcmpg,
468 Dcmpl,
469 Dcmpg,
470
471 Ifeq { target: String },
473 Ifne { target: String },
474 Iflt { target: String },
475 Ifge { target: String },
476 Ifgt { target: String },
477 Ifle { target: String },
478 IfIcmpeq { target: String },
479 IfIcmpne { target: String },
480 IfIcmplt { target: String },
481 IfIcmpge { target: String },
482 IfIcmpgt { target: String },
483 IfIcmple { target: String },
484 IfAcmpeq { target: String },
485 IfAcmpne { target: String },
486 Goto { target: String },
487 Jsr { target: String },
488 Ret { index: u16 },
489
490 Ireturn,
492 Lreturn,
493 Freturn,
494 Dreturn,
495 Areturn,
496 Return,
497
498 Getstatic { class_name: String, field_name: String, descriptor: String },
500 Putstatic { class_name: String, field_name: String, descriptor: String },
501 Getfield { class_name: String, field_name: String, descriptor: String },
502 Putfield { class_name: String, field_name: String, descriptor: String },
503
504 Invokevirtual { class_name: String, method_name: String, descriptor: String },
506 Invokespecial { class_name: String, method_name: String, descriptor: String },
507 Invokestatic { class_name: String, method_name: String, descriptor: String },
508 Invokeinterface { class_name: String, method_name: String, descriptor: String },
509 Invokedynamic { class_name: String, method_name: String, descriptor: String },
510
511 New { class_name: String },
513 Newarray { atype: u8 },
514 Anewarray { class_name: String },
515 Arraylength,
516 Athrow,
517 Checkcast { class_name: String },
518 Instanceof { class_name: String },
519 Monitorenter,
520 Monitorexit,
521
522 Wide,
524 Multianewarray { class_name: String, dimensions: u8 },
525 Ifnull { target: String },
526 Ifnonnull { target: String },
527 GotoW { target: String },
528 JsrW { target: String },
529}
530
531impl JvmInstruction {
532 pub fn to_byte(&self) -> u8 {
534 match self {
535 JvmInstruction::Nop => 0x00,
536 JvmInstruction::AconstNull => 0x01,
537 JvmInstruction::IconstM1 => 0x02,
538 JvmInstruction::Iconst0 => 0x03,
539 JvmInstruction::Iconst1 => 0x04,
540 JvmInstruction::Iconst2 => 0x05,
541 JvmInstruction::Iconst3 => 0x06,
542 JvmInstruction::Iconst4 => 0x07,
543 JvmInstruction::Iconst5 => 0x08,
544 JvmInstruction::Lconst0 => 0x09,
545 JvmInstruction::Lconst1 => 0x0A,
546 JvmInstruction::Fconst0 => 0x0B,
547 JvmInstruction::Fconst1 => 0x0C,
548 JvmInstruction::Fconst2 => 0x0D,
549 JvmInstruction::Dconst0 => 0x0E,
550 JvmInstruction::Dconst1 => 0x0F,
551 JvmInstruction::Bipush { .. } => 0x10,
552 JvmInstruction::Sipush { .. } => 0x11,
553 JvmInstruction::Ldc { .. } => 0x12,
554 JvmInstruction::LdcW { .. } => 0x13,
555 JvmInstruction::Ldc2W { .. } => 0x14,
556 JvmInstruction::Iload { .. } => 0x15,
557 JvmInstruction::Lload { .. } => 0x16,
558 JvmInstruction::Fload { .. } => 0x17,
559 JvmInstruction::Dload { .. } => 0x18,
560 JvmInstruction::Aload { .. } => 0x19,
561 JvmInstruction::Iload0 => 0x1A,
562 JvmInstruction::Iload1 => 0x1B,
563 JvmInstruction::Iload2 => 0x1C,
564 JvmInstruction::Iload3 => 0x1D,
565 JvmInstruction::Lload0 => 0x1E,
566 JvmInstruction::Lload1 => 0x1F,
567 JvmInstruction::Lload2 => 0x20,
568 JvmInstruction::Lload3 => 0x21,
569 JvmInstruction::Fload0 => 0x22,
570 JvmInstruction::Fload1 => 0x23,
571 JvmInstruction::Fload2 => 0x24,
572 JvmInstruction::Fload3 => 0x25,
573 JvmInstruction::Dload0 => 0x26,
574 JvmInstruction::Dload1 => 0x27,
575 JvmInstruction::Dload2 => 0x28,
576 JvmInstruction::Dload3 => 0x29,
577 JvmInstruction::Aload0 => 0x2A,
578 JvmInstruction::Aload1 => 0x2B,
579 JvmInstruction::Aload2 => 0x2C,
580 JvmInstruction::Aload3 => 0x2D,
581 JvmInstruction::Istore { .. } => 0x36,
582 JvmInstruction::Lstore { .. } => 0x37,
583 JvmInstruction::Fstore { .. } => 0x38,
584 JvmInstruction::Dstore { .. } => 0x39,
585 JvmInstruction::Astore { .. } => 0x3A,
586 JvmInstruction::Istore0 => 0x3B,
587 JvmInstruction::Istore1 => 0x3C,
588 JvmInstruction::Istore2 => 0x3D,
589 JvmInstruction::Istore3 => 0x3E,
590 JvmInstruction::Lstore0 => 0x3F,
591 JvmInstruction::Lstore1 => 0x40,
592 JvmInstruction::Lstore2 => 0x41,
593 JvmInstruction::Lstore3 => 0x42,
594 JvmInstruction::Fstore0 => 0x43,
595 JvmInstruction::Fstore1 => 0x44,
596 JvmInstruction::Fstore2 => 0x45,
597 JvmInstruction::Fstore3 => 0x46,
598 JvmInstruction::Dstore0 => 0x47,
599 JvmInstruction::Dstore1 => 0x48,
600 JvmInstruction::Dstore2 => 0x49,
601 JvmInstruction::Dstore3 => 0x4A,
602 JvmInstruction::Astore0 => 0x4B,
603 JvmInstruction::Astore1 => 0x4C,
604 JvmInstruction::Astore2 => 0x4D,
605 JvmInstruction::Astore3 => 0x4E,
606 JvmInstruction::Pop => 0x57,
607 JvmInstruction::Pop2 => 0x58,
608 JvmInstruction::Dup => 0x59,
609 JvmInstruction::DupX1 => 0x5A,
610 JvmInstruction::DupX2 => 0x5B,
611 JvmInstruction::Dup2 => 0x5C,
612 JvmInstruction::Dup2X1 => 0x5D,
613 JvmInstruction::Dup2X2 => 0x5E,
614 JvmInstruction::Swap => 0x5F,
615 JvmInstruction::Iadd => 0x60,
616 JvmInstruction::Ladd => 0x61,
617 JvmInstruction::Fadd => 0x62,
618 JvmInstruction::Dadd => 0x63,
619 JvmInstruction::Isub => 0x64,
620 JvmInstruction::Lsub => 0x65,
621 JvmInstruction::Fsub => 0x66,
622 JvmInstruction::Dsub => 0x67,
623 JvmInstruction::Imul => 0x68,
624 JvmInstruction::Lmul => 0x69,
625 JvmInstruction::Fmul => 0x6A,
626 JvmInstruction::Dmul => 0x6B,
627 JvmInstruction::Idiv => 0x6C,
628 JvmInstruction::Ldiv => 0x6D,
629 JvmInstruction::Fdiv => 0x6E,
630 JvmInstruction::Ddiv => 0x6F,
631 JvmInstruction::Irem => 0x70,
632 JvmInstruction::Lrem => 0x71,
633 JvmInstruction::Frem => 0x72,
634 JvmInstruction::Drem => 0x73,
635 JvmInstruction::Ineg => 0x74,
636 JvmInstruction::Lneg => 0x75,
637 JvmInstruction::Fneg => 0x76,
638 JvmInstruction::Dneg => 0x77,
639 JvmInstruction::Ishl => 0x78,
640 JvmInstruction::Lshl => 0x79,
641 JvmInstruction::Ishr => 0x7A,
642 JvmInstruction::Lshr => 0x7B,
643 JvmInstruction::Iushr => 0x7C,
644 JvmInstruction::Lushr => 0x7D,
645 JvmInstruction::Iand => 0x7E,
646 JvmInstruction::Land => 0x7F,
647 JvmInstruction::Ior => 0x80,
648 JvmInstruction::Lor => 0x81,
649 JvmInstruction::Ixor => 0x82,
650 JvmInstruction::Lxor => 0x83,
651 JvmInstruction::Lcmp => 0x94,
652 JvmInstruction::Fcmpl => 0x95,
653 JvmInstruction::Fcmpg => 0x96,
654 JvmInstruction::Dcmpl => 0x97,
655 JvmInstruction::Dcmpg => 0x98,
656 JvmInstruction::Ifeq { .. } => 0x99,
657 JvmInstruction::Ifne { .. } => 0x9A,
658 JvmInstruction::Iflt { .. } => 0x9B,
659 JvmInstruction::Ifge { .. } => 0x9C,
660 JvmInstruction::Ifgt { .. } => 0x9D,
661 JvmInstruction::Ifle { .. } => 0x9E,
662 JvmInstruction::IfIcmpeq { .. } => 0x9F,
663 JvmInstruction::IfIcmpne { .. } => 0xA0,
664 JvmInstruction::IfIcmplt { .. } => 0xA1,
665 JvmInstruction::IfIcmpge { .. } => 0xA2,
666 JvmInstruction::IfIcmpgt { .. } => 0xA3,
667 JvmInstruction::IfIcmple { .. } => 0xA4,
668 JvmInstruction::IfAcmpeq { .. } => 0xA5,
669 JvmInstruction::IfAcmpne { .. } => 0xA6,
670 JvmInstruction::Goto { .. } => 0xA7,
671 JvmInstruction::Jsr { .. } => 0xA8,
672 JvmInstruction::Ret { .. } => 0xA9,
673 JvmInstruction::Ireturn => 0xAC,
674 JvmInstruction::Lreturn => 0xAD,
675 JvmInstruction::Freturn => 0xAE,
676 JvmInstruction::Dreturn => 0xAF,
677 JvmInstruction::Areturn => 0xB0,
678 JvmInstruction::Return => 0xB1,
679 JvmInstruction::Getstatic { .. } => 0xB2,
680 JvmInstruction::Putstatic { .. } => 0xB3,
681 JvmInstruction::Getfield { .. } => 0xB4,
682 JvmInstruction::Putfield { .. } => 0xB5,
683 JvmInstruction::Invokevirtual { .. } => 0xB6,
684 JvmInstruction::Invokespecial { .. } => 0xB7,
685 JvmInstruction::Invokestatic { .. } => 0xB8,
686 JvmInstruction::Invokeinterface { .. } => 0xB9,
687 JvmInstruction::Invokedynamic { .. } => 0xBA,
688 JvmInstruction::New { .. } => 0xBB,
689 JvmInstruction::Newarray { .. } => 0xBC,
690 JvmInstruction::Anewarray { .. } => 0xBD,
691 JvmInstruction::Arraylength => 0xBE,
692 JvmInstruction::Athrow => 0xBF,
693 JvmInstruction::Checkcast { .. } => 0xC0,
694 JvmInstruction::Instanceof { .. } => 0xC1,
695 JvmInstruction::Monitorenter => 0xC2,
696 JvmInstruction::Monitorexit => 0xC3,
697 JvmInstruction::Wide => 0xC4,
698 JvmInstruction::Multianewarray { .. } => 0xC5,
699 JvmInstruction::Ifnull { .. } => 0xC6,
700 JvmInstruction::Ifnonnull { .. } => 0xC7,
701 JvmInstruction::GotoW { .. } => 0xC8,
702 JvmInstruction::JsrW { .. } => 0xC9,
703 }
704 }
705}
706
707
708#[derive(Debug, Clone)]
710pub struct JvmExceptionHandler {
711 pub start_pc: u16,
713 pub end_pc: u16,
715 pub handler_pc: u16,
717 pub catch_type: Option<String>,
719}
720
721#[derive(Debug, Clone)]
723pub enum JvmAttribute {
724 SourceFile { filename: String },
726 Code {
728 max_stack: u16,
729 max_locals: u16,
730 code: Vec<u8>,
731 exception_table: Vec<JvmExceptionHandler>,
732 attributes: Vec<JvmAttribute>,
733 },
734 ConstantValue { value: JvmConstantPoolEntry },
736 Signature { signature: String },
738 Exceptions { exceptions: Vec<String> },
740 LineNumberTable { entries: Vec<(u16, u16)> },
742 LocalVariableTable { entries: Vec<JvmLocalVariable> },
744 Unknown { name: String, data: Vec<u8> },
746}
747
748#[derive(Debug, Clone)]
750pub struct JvmLocalVariable {
751 pub start_pc: u16,
753 pub length: u16,
755 pub name: String,
757 pub descriptor: String,
759 pub index: u16,
761}
762
763impl JvmProgram {
764 pub fn new(name: String) -> Self {
766 Self {
767 name,
768 access_flags: JvmAccessFlags::default(),
769 super_class: Some("java/lang/Object".to_string()),
770 interfaces: Vec::new(),
771 fields: Vec::new(),
772 methods: Vec::new(),
773 attributes: Vec::new(),
774 constant_pool: JvmConstantPool::new(),
775 version: JvmVersion { major: 65, minor: 0 }, source_file: None,
777 }
778 }
779
780 pub fn add_method(&mut self, method: JvmMethod) {
782 self.methods.push(method);
783 }
784
785 pub fn add_field(&mut self, field: JvmField) {
787 self.fields.push(field);
788 }
789
790 pub fn set_source_file(&mut self, filename: String) {
792 self.source_file = Some(filename.clone());
793 self.attributes.push(JvmAttribute::SourceFile { filename });
794 }
795
796 pub fn validate(&self) -> Result<()> {
798 if self.name.is_empty() {
800 return Err(GaiaError::custom_error("Class name cannot be empty".to_string()));
801 }
802
803 for method in &self.methods {
805 method.validate()?;
806 }
807
808 for field in &self.fields {
810 field.validate()?;
811 }
812
813 Ok(())
814 }
815}
816
817impl JvmConstantPool {
818 pub fn new() -> Self {
820 Self { symbol_table: HashMap::new(), entries: Vec::new() }
821 }
822
823 pub fn add_entry(&mut self, entry: JvmConstantPoolEntry) -> u16 {
825 for (index, existing_entry) in self.entries.iter().enumerate() {
827 if existing_entry == &entry {
828 return (index + 1) as u16; }
830 }
831
832 let index = (self.entries.len() + 1) as u16;
833 self.entries.push(entry);
834 index
835 }
836
837 pub fn find_symbol(&self, symbol: &str) -> Option<u16> {
839 self.symbol_table.get(symbol).copied()
840 }
841
842 pub fn add_symbol(&mut self, symbol: String, index: u16) {
844 self.symbol_table.insert(symbol, index);
845 }
846}
847
848impl JvmMethod {
849 pub fn new(name: String, descriptor: String) -> Self {
851 Self {
852 name,
853 descriptor,
854 access_flags: JvmAccessFlags::default(),
855 instructions: Vec::new(),
856 max_stack: 0,
857 max_locals: 0,
858 exception_table: Vec::new(),
859 attributes: Vec::new(),
860 }
861 }
862
863 pub fn with_access_flags(mut self, access_flags: JvmAccessFlags) -> Self {
865 self.access_flags = access_flags;
866 self
867 }
868
869 pub fn with_public(mut self) -> Self {
871 self.access_flags |= JvmAccessFlags::PUBLIC;
872 self
873 }
874
875 pub fn with_private(mut self) -> Self {
877 self.access_flags |= JvmAccessFlags::PRIVATE;
878 self
879 }
880
881 pub fn with_protected(mut self) -> Self {
883 self.access_flags |= JvmAccessFlags::PROTECTED;
884 self
885 }
886
887 pub fn with_static(mut self) -> Self {
889 self.access_flags |= JvmAccessFlags::STATIC;
890 self
891 }
892
893 pub fn with_final(mut self) -> Self {
895 self.access_flags |= JvmAccessFlags::FINAL;
896 self
897 }
898
899 pub fn with_abstract(mut self) -> Self {
901 self.access_flags |= JvmAccessFlags::ABSTRACT;
902 self
903 }
904
905 pub fn with_max_stack(mut self, max_stack: u16) -> Self {
907 self.max_stack = max_stack;
908 self
909 }
910
911 pub fn with_max_locals(mut self, max_locals: u16) -> Self {
913 self.max_locals = max_locals;
914 self
915 }
916
917 pub fn with_instruction(mut self, instruction: JvmInstruction) -> Self {
919 self.instructions.push(instruction);
920 self
921 }
922
923 pub fn with_instructions(mut self, instructions: Vec<JvmInstruction>) -> Self {
925 self.instructions.extend(instructions);
926 self
927 }
928
929 pub fn with_exception_handler(mut self, handler: JvmExceptionHandler) -> Self {
931 self.exception_table.push(handler);
932 self
933 }
934
935 pub fn with_attribute(mut self, attribute: JvmAttribute) -> Self {
937 self.attributes.push(attribute);
938 self
939 }
940
941 pub fn with_attributes(mut self, attributes: Vec<JvmAttribute>) -> Self {
943 self.attributes.extend(attributes);
944 self
945 }
946
947 pub fn add_instruction(&mut self, instruction: JvmInstruction) {
949 self.instructions.push(instruction);
950 }
951
952 pub fn validate(&self) -> Result<()> {
954 if self.name.is_empty() {
955 return Err(GaiaError::custom_error("Method name cannot be empty".to_string()));
956 }
957 if self.descriptor.is_empty() {
958 return Err(GaiaError::custom_error("Method descriptor cannot be empty".to_string()));
959 }
960 Ok(())
961 }
962}
963
964impl JvmField {
965 pub fn new(name: String, descriptor: String) -> Self {
967 Self { name, descriptor, access_flags: JvmAccessFlags::default(), constant_value: None, attributes: Vec::new() }
968 }
969
970 pub fn with_access_flags(mut self, access_flags: JvmAccessFlags) -> Self {
972 self.access_flags = access_flags;
973 self
974 }
975
976 pub fn with_public(mut self) -> Self {
978 self.access_flags |= JvmAccessFlags::PUBLIC;
979 self
980 }
981
982 pub fn with_private(mut self) -> Self {
984 self.access_flags |= JvmAccessFlags::PRIVATE;
985 self
986 }
987
988 pub fn with_protected(mut self) -> Self {
990 self.access_flags |= JvmAccessFlags::PROTECTED;
991 self
992 }
993
994 pub fn with_static(mut self) -> Self {
996 self.access_flags |= JvmAccessFlags::STATIC;
997 self
998 }
999
1000 pub fn with_final(mut self) -> Self {
1002 self.access_flags |= JvmAccessFlags::FINAL;
1003 self
1004 }
1005
1006 pub fn with_volatile(mut self) -> Self {
1008 self.access_flags |= JvmAccessFlags::VOLATILE;
1009 self
1010 }
1011
1012 pub fn with_transient(mut self) -> Self {
1014 self.access_flags |= JvmAccessFlags::TRANSIENT;
1015 self
1016 }
1017
1018 pub fn with_constant_value(mut self, value: JvmConstantPoolEntry) -> Self {
1020 self.constant_value = Some(value);
1021 self
1022 }
1023
1024 pub fn with_attribute(mut self, attribute: JvmAttribute) -> Self {
1026 self.attributes.push(attribute);
1027 self
1028 }
1029
1030 pub fn with_attributes(mut self, attributes: Vec<JvmAttribute>) -> Self {
1032 self.attributes.extend(attributes);
1033 self
1034 }
1035
1036 pub fn validate(&self) -> Result<()> {
1038 if self.name.is_empty() {
1039 return Err(GaiaError::custom_error("Field name cannot be empty".to_string()));
1040 }
1041 if self.descriptor.is_empty() {
1042 return Err(GaiaError::custom_error("Field descriptor cannot be empty".to_string()));
1043 }
1044 Ok(())
1045 }
1046}
1047
1048impl Default for JvmAccessFlags {
1049 fn default() -> Self {
1050 Self {
1051 is_public: false,
1052 is_final: false,
1053 is_super: true, is_interface: false,
1055 is_abstract: false,
1056 is_synthetic: false,
1057 is_annotation: false,
1058 is_enum: false,
1059 is_static: false,
1060 is_private: false,
1061 is_protected: false,
1062 is_volatile: false,
1063 is_transient: false,
1064 }
1065 }
1066}
1067
1068impl JvmAccessFlags {
1069 pub fn from_modifiers(modifiers: &[String]) -> Self {
1071 let mut flags = Self::default();
1072
1073 for modifier in modifiers {
1074 match modifier.as_str() {
1075 "public" => flags.is_public = true,
1076 "private" => flags.is_private = true,
1077 "protected" => flags.is_protected = true,
1078 "static" => flags.is_static = true,
1079 "final" => flags.is_final = true,
1080 "super" => flags.is_super = true,
1081 "interface" => flags.is_interface = true,
1082 "abstract" => flags.is_abstract = true,
1083 "synthetic" => flags.is_synthetic = true,
1084 "annotation" => flags.is_annotation = true,
1085 "enum" => flags.is_enum = true,
1086 "volatile" => flags.is_volatile = true,
1087 "transient" => flags.is_transient = true,
1088 _ => {} }
1090 }
1091
1092 flags
1093 }
1094
1095 pub fn from_flags(flags: u16) -> Self {
1097 Self {
1098 is_public: (flags & 0x0001) != 0,
1099 is_private: (flags & 0x0002) != 0,
1100 is_protected: (flags & 0x0004) != 0,
1101 is_static: (flags & 0x0008) != 0,
1102 is_final: (flags & 0x0010) != 0,
1103 is_super: (flags & 0x0020) != 0,
1104 is_volatile: (flags & 0x0040) != 0,
1105 is_transient: (flags & 0x0080) != 0,
1106 is_interface: (flags & 0x0200) != 0,
1107 is_abstract: (flags & 0x0400) != 0,
1108 is_synthetic: (flags & 0x1000) != 0,
1109 is_annotation: (flags & 0x2000) != 0,
1110 is_enum: (flags & 0x4000) != 0,
1111 }
1112 }
1113
1114 pub fn to_modifiers(&self) -> Vec<String> {
1116 let mut modifiers = Vec::new();
1117 if self.is_public {
1118 modifiers.push("public".to_string());
1119 }
1120 if self.is_private {
1121 modifiers.push("private".to_string());
1122 }
1123 if self.is_protected {
1124 modifiers.push("protected".to_string());
1125 }
1126 if self.is_static {
1127 modifiers.push("static".to_string());
1128 }
1129 if self.is_final {
1130 modifiers.push("final".to_string());
1131 }
1132 if self.is_super {
1133 modifiers.push("super".to_string());
1134 }
1135 if self.is_interface {
1136 modifiers.push("interface".to_string());
1137 }
1138 if self.is_abstract {
1139 modifiers.push("abstract".to_string());
1140 }
1141 if self.is_synthetic {
1142 modifiers.push("synthetic".to_string());
1143 }
1144 if self.is_annotation {
1145 modifiers.push("annotation".to_string());
1146 }
1147 if self.is_enum {
1148 modifiers.push("enum".to_string());
1149 }
1150 if self.is_volatile {
1151 modifiers.push("volatile".to_string());
1152 }
1153 if self.is_transient {
1154 modifiers.push("transient".to_string());
1155 }
1156 modifiers
1157 }
1158
1159 pub fn to_flags(&self) -> u16 {
1161 let mut flags = 0u16;
1162
1163 if self.is_public {
1164 flags |= 0x0001;
1165 }
1166 if self.is_private {
1167 flags |= 0x0002;
1168 }
1169 if self.is_protected {
1170 flags |= 0x0004;
1171 }
1172 if self.is_static {
1173 flags |= 0x0008;
1174 }
1175 if self.is_final {
1176 flags |= 0x0010;
1177 }
1178 if self.is_super {
1179 flags |= 0x0020;
1180 }
1181 if self.is_volatile {
1182 flags |= 0x0040;
1183 }
1184 if self.is_transient {
1185 flags |= 0x0080;
1186 }
1187 if self.is_interface {
1188 flags |= 0x0200;
1189 }
1190 if self.is_abstract {
1191 flags |= 0x0400;
1192 }
1193 if self.is_synthetic {
1194 flags |= 0x1000;
1195 }
1196 if self.is_annotation {
1197 flags |= 0x2000;
1198 }
1199 if self.is_enum {
1200 flags |= 0x4000;
1201 }
1202
1203 flags
1204 }
1205}
1206
1207
1208
1209pub use JvmConstantPoolEntry as ConstantPoolEntry;
1211
1212#[derive(Debug, Clone, PartialEq)]
1214pub struct JvmInstructionCompat {
1215 pub opcode: u8,
1217 pub operands: Vec<u8>,
1219 pub metadata: Option<String>,
1221}
1222
1223impl JvmInstructionCompat {
1224 pub fn new(opcode: u8, operands: Vec<u8>) -> Self {
1226 Self { opcode, operands, metadata: None }
1227 }
1228
1229 pub fn with_metadata(opcode: u8, operands: Vec<u8>, metadata: String) -> Self {
1231 Self { opcode, operands, metadata: Some(metadata) }
1232 }
1233
1234 pub fn to_bytes(&self) -> Vec<u8> {
1236 let mut bytes = vec![self.opcode];
1237 bytes.extend_from_slice(&self.operands);
1238 bytes
1239 }
1240
1241 pub fn len(&self) -> usize {
1243 1 + self.operands.len()
1244 }
1245
1246 pub fn is_empty(&self) -> bool {
1248 false }
1250}
1251
1252#[derive(Debug, Clone)]
1254pub struct JvmClassCompat {
1255 pub magic: u32,
1257 pub minor_version: u16,
1259 pub major_version: u16,
1261 pub constant_pool: Vec<ConstantPoolEntry>,
1263 pub access_flags: u16,
1265 pub this_class: u16,
1267 pub super_class: u16,
1269 pub interfaces: Vec<u16>,
1271 pub fields: Vec<JvmFieldCompat>,
1273 pub methods: Vec<JvmMethodCompat>,
1275}
1276
1277impl Default for JvmClassCompat {
1278 fn default() -> Self {
1279 Self {
1280 magic: 0xCAFEBABE,
1281 minor_version: 0,
1282 major_version: 65, constant_pool: Vec::new(),
1284 access_flags: 0x0021, this_class: 0,
1286 super_class: 0,
1287 interfaces: Vec::new(),
1288 fields: Vec::new(),
1289 methods: Vec::new(),
1290 }
1291 }
1292}
1293
1294#[derive(Debug, Clone)]
1296pub struct JvmMethodCompat {
1297 pub access_flags: u16,
1299 pub name_index: u16,
1301 pub descriptor_index: u16,
1303 pub instructions: Vec<JvmInstructionCompat>,
1305 pub max_stack: u16,
1307 pub max_locals: u16,
1309}
1310
1311impl JvmMethodCompat {
1312 pub fn new(name_index: u16, descriptor_index: u16) -> Self {
1314 Self {
1315 access_flags: 0x0001, name_index,
1317 descriptor_index,
1318 instructions: Vec::new(),
1319 max_stack: 2,
1320 max_locals: 1,
1321 }
1322 }
1323
1324 pub fn add_instruction(&mut self, instruction: JvmInstructionCompat) {
1326 self.instructions.push(instruction);
1327 }
1328
1329 pub fn code_length(&self) -> u32 {
1331 self.instructions.iter().map(|i| i.len() as u32).sum()
1332 }
1333}
1334
1335#[derive(Debug, Clone)]
1337pub struct JvmFieldCompat {
1338 pub access_flags: u16,
1340 pub name_index: u16,
1342 pub descriptor_index: u16,
1344}
1345
1346pub mod opcodes {
1348 pub const ACONST_NULL: u8 = 0x01;
1349 pub const ICONST_M1: u8 = 0x02;
1350 pub const ICONST_0: u8 = 0x03;
1351 pub const ICONST_1: u8 = 0x04;
1352 pub const ICONST_2: u8 = 0x05;
1353 pub const ICONST_3: u8 = 0x06;
1354 pub const ICONST_4: u8 = 0x07;
1355 pub const ICONST_5: u8 = 0x08;
1356 pub const LCONST_0: u8 = 0x09;
1357 pub const LCONST_1: u8 = 0x0A;
1358 pub const FCONST_0: u8 = 0x0B;
1359 pub const FCONST_1: u8 = 0x0C;
1360 pub const FCONST_2: u8 = 0x0D;
1361 pub const DCONST_0: u8 = 0x0E;
1362 pub const DCONST_1: u8 = 0x0F;
1363 pub const BIPUSH: u8 = 0x10;
1364 pub const SIPUSH: u8 = 0x11;
1365 pub const LDC: u8 = 0x12;
1366 pub const LDC_W: u8 = 0x13;
1367 pub const LDC2_W: u8 = 0x14;
1368
1369 pub const ILOAD: u8 = 0x15;
1371 pub const LLOAD: u8 = 0x16;
1372 pub const FLOAD: u8 = 0x17;
1373 pub const DLOAD: u8 = 0x18;
1374 pub const ALOAD: u8 = 0x19;
1375 pub const ILOAD_0: u8 = 0x1A;
1376 pub const ILOAD_1: u8 = 0x1B;
1377 pub const ILOAD_2: u8 = 0x1C;
1378 pub const ILOAD_3: u8 = 0x1D;
1379 pub const LLOAD_0: u8 = 0x1E;
1380 pub const LLOAD_1: u8 = 0x1F;
1381 pub const LLOAD_2: u8 = 0x20;
1382 pub const LLOAD_3: u8 = 0x21;
1383 pub const FLOAD_0: u8 = 0x22;
1384 pub const FLOAD_1: u8 = 0x23;
1385 pub const FLOAD_2: u8 = 0x24;
1386 pub const FLOAD_3: u8 = 0x25;
1387 pub const DLOAD_0: u8 = 0x26;
1388 pub const DLOAD_1: u8 = 0x27;
1389 pub const DLOAD_2: u8 = 0x28;
1390 pub const DLOAD_3: u8 = 0x29;
1391 pub const ALOAD_0: u8 = 0x2A;
1392 pub const ALOAD_1: u8 = 0x2B;
1393 pub const ALOAD_2: u8 = 0x2C;
1394 pub const ALOAD_3: u8 = 0x2D;
1395
1396 pub const ISTORE: u8 = 0x36;
1398 pub const LSTORE: u8 = 0x37;
1399 pub const FSTORE: u8 = 0x38;
1400 pub const DSTORE: u8 = 0x39;
1401 pub const ASTORE: u8 = 0x3A;
1402 pub const ISTORE_0: u8 = 0x3B;
1403 pub const ISTORE_1: u8 = 0x3C;
1404 pub const ISTORE_2: u8 = 0x3D;
1405 pub const ISTORE_3: u8 = 0x3E;
1406 pub const LSTORE_0: u8 = 0x3F;
1407 pub const LSTORE_1: u8 = 0x40;
1408 pub const LSTORE_2: u8 = 0x41;
1409 pub const LSTORE_3: u8 = 0x42;
1410 pub const FSTORE_0: u8 = 0x43;
1411 pub const FSTORE_1: u8 = 0x44;
1412 pub const FSTORE_2: u8 = 0x45;
1413 pub const FSTORE_3: u8 = 0x46;
1414 pub const DSTORE_0: u8 = 0x47;
1415 pub const DSTORE_1: u8 = 0x48;
1416 pub const DSTORE_2: u8 = 0x49;
1417 pub const DSTORE_3: u8 = 0x4A;
1418 pub const ASTORE_0: u8 = 0x4B;
1419 pub const ASTORE_1: u8 = 0x4C;
1420 pub const ASTORE_2: u8 = 0x4D;
1421 pub const ASTORE_3: u8 = 0x4E;
1422
1423 pub const POP: u8 = 0x57;
1425 pub const POP2: u8 = 0x58;
1426 pub const DUP: u8 = 0x59;
1427 pub const DUP_X1: u8 = 0x5A;
1428 pub const DUP_X2: u8 = 0x5B;
1429 pub const DUP2: u8 = 0x5C;
1430 pub const DUP2_X1: u8 = 0x5D;
1431 pub const DUP2_X2: u8 = 0x5E;
1432 pub const SWAP: u8 = 0x5F;
1433
1434 pub const IADD: u8 = 0x60;
1436 pub const LADD: u8 = 0x61;
1437 pub const FADD: u8 = 0x62;
1438 pub const DADD: u8 = 0x63;
1439 pub const ISUB: u8 = 0x64;
1440 pub const LSUB: u8 = 0x65;
1441 pub const FSUB: u8 = 0x66;
1442 pub const DSUB: u8 = 0x67;
1443 pub const IMUL: u8 = 0x68;
1444 pub const LMUL: u8 = 0x69;
1445 pub const FMUL: u8 = 0x6A;
1446 pub const DMUL: u8 = 0x6B;
1447 pub const IDIV: u8 = 0x6C;
1448 pub const LDIV: u8 = 0x6D;
1449 pub const FDIV: u8 = 0x6E;
1450 pub const DDIV: u8 = 0x6F;
1451
1452 pub const INVOKEVIRTUAL: u8 = 0xB6;
1454 pub const INVOKESPECIAL: u8 = 0xB7;
1455 pub const INVOKESTATIC: u8 = 0xB8;
1456 pub const INVOKEINTERFACE: u8 = 0xB9;
1457
1458 pub const IRETURN: u8 = 0xAC;
1460 pub const LRETURN: u8 = 0xAD;
1461 pub const FRETURN: u8 = 0xAE;
1462 pub const DRETURN: u8 = 0xAF;
1463 pub const ARETURN: u8 = 0xB0;
1464 pub const RETURN: u8 = 0xB1;
1465
1466 pub const GETSTATIC: u8 = 0xB2;
1468 pub const PUTSTATIC: u8 = 0xB3;
1469 pub const GETFIELD: u8 = 0x84;
1470 pub const PUTFIELD: u8 = 0xB5;
1471
1472 pub const NOP: u8 = 0x00;
1474}