1
2#[derive(Debug, PartialEq)]
8pub struct Classfile {
9 pub version: ClassfileVersion,
10 pub constant_pool: ConstantPool,
11 pub access_flags: AccessFlags,
12 pub this_class: ConstantPoolIndex,
13 pub super_class: ConstantPoolIndex,
14 pub interfaces: Vec<ConstantPoolIndex>,
15 pub fields: Vec<Field>,
16 pub methods: Vec<Method>,
17 pub attributes: Vec<Attribute>
18}
19
20impl Classfile {
21 pub fn new() -> Classfile {
23 Classfile::default()
24 }
25}
26
27impl Default for Classfile {
28 fn default() -> Self {
29 Classfile {
30 version: ClassfileVersion::default(),
31 constant_pool: ConstantPool::default(),
32 access_flags: AccessFlags::default(),
33 this_class: ConstantPoolIndex::default(),
34 super_class: ConstantPoolIndex::default(),
35 interfaces: vec![],
36 fields: vec![],
37 methods: vec![],
38 attributes: vec![]
39 }
40 }
41}
42
43#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
46pub struct ClassfileVersion {
47 pub minor_version: u16,
48 pub major_version: u16
49}
50
51impl ClassfileVersion {
52 pub fn new(major_version: u16, minor_version: u16) -> ClassfileVersion {
53 ClassfileVersion { major_version: major_version, minor_version: minor_version }
54 }
55}
56
57impl Default for ClassfileVersion {
58 fn default() -> Self {
59 const DEFAULT_MAJOR_VERSION: u16 = 52;
60 const DEFAULT_MINOR_VERSION: u16 = 0;
61
62 ClassfileVersion { major_version: DEFAULT_MAJOR_VERSION, minor_version: DEFAULT_MINOR_VERSION }
63 }
64}
65
66#[derive(Debug, PartialEq)]
70pub struct ConstantPool {
71 pub constants: Vec<Constant>
72}
73
74impl ConstantPool {
75 pub fn new(constants: Vec<Constant>) -> ConstantPool {
76 ConstantPool {
77 constants: constants
78 }
79 }
80
81 pub fn get_utf8(&self, idx: u16) -> Option<&Vec<u8>> {
82 match self.constants.get(idx as usize) {
83 Some(constant) => match constant {
84 &Constant::Utf8(ref bytes) => Some(bytes),
85 _ => None
86 },
87 _ => None
88 }
89 }
90
91 pub fn get_utf8_string(&self, idx: u16) -> Option<String> {
92 match self.get_utf8(idx) {
93 Some(bytes) => match String::from_utf8(bytes.clone()) {
94 Ok(string) => Some(string),
95 _ => None
96 },
97 _ => None
98 }
99 }
100
101 pub fn find_ut8_index(&self, utf8: &'static str) -> Option<usize> {
102 for i in 0..self.constants.len() {
103 match self.constants[i] {
104 Constant::Utf8(ref bytes) => {
105 if bytes.as_slice() == utf8.as_bytes() {
106 return Some(i);
107 }
108 },
109 _ => ()
110 }
111 }
112 None
113 }
114
115 pub fn get_utf8_index(&self, utf8: &'static str) -> usize {
116 self.find_ut8_index(utf8).unwrap_or(0)
117 }
118
119 pub fn resolve_index(&self, idx: &ConstantPoolIndex) -> Option<&Constant> {
120 self.constants.get(idx.idx)
121 }
122
123 pub fn has_constant(&self, constant: &Constant) -> bool {
124 self.constants.iter().any(|item| *constant == *item)
125 }
126
127 pub fn add_constant(&mut self, constant: Constant) -> ConstantPoolIndex {
128 self.constants.push(constant);
129 ConstantPoolIndex::new(self.cp_len())
130 }
131
132 pub fn get_constant_index(&self, constant: &Constant) -> Option<ConstantPoolIndex> {
133 if self.has_constant(constant) {
134 Some(ConstantPoolIndex::new(self.constants.iter().take_while(|item| **item != *constant).map(|item| item.cp_size()).fold(1, |acc, x| acc + x)))
135 } else {
136 None
137 }
138 }
139
140 pub fn cp_len(&self) -> usize {
141 self.constants.len()
143 }
144}
145
146impl Default for ConstantPool {
147 fn default() -> Self {
148 ConstantPool {
149 constants: vec![]
150 }
151 }
152}
153
154#[derive(Default, Debug, PartialEq)]
155pub struct ConstantPoolIndex {
156 pub idx: usize
157}
158
159impl ConstantPoolIndex {
160 pub fn new(idx: usize) -> Self {
161 ConstantPoolIndex { idx: idx }
162 }
163}
164
165#[derive(Debug, PartialEq)]
166pub enum Constant {
167 Utf8(Vec<u8>),
168 Integer(u32),
169 Float(u32),
170 Long(u64),
171 Double(u64),
172 Class(ConstantPoolIndex),
173 FieldRef { class_index: ConstantPoolIndex, name_and_type_index: ConstantPoolIndex },
174 MethodRef { class_index: ConstantPoolIndex, name_and_type_index: ConstantPoolIndex },
175 InterfaceMethodRef { class_index: ConstantPoolIndex, name_and_type_index: ConstantPoolIndex },
176 String(ConstantPoolIndex),
177 NameAndType { name_index: ConstantPoolIndex, descriptor_index: ConstantPoolIndex },
178 MethodHandle { reference_kind: ReferenceKind, reference_index: ConstantPoolIndex },
179 MethodType(ConstantPoolIndex),
180 InvokeDynamic { bootstrap_method_attr_index: ConstantPoolIndex, name_and_type_index: ConstantPoolIndex },
181 Unknown(u8),
182 Placeholder
183}
184
185impl Constant {
186 pub fn cp_size(&self) -> usize {
187 match self {
188 &Constant::Long(_) => 2,
189 &Constant::Double(_) => 2,
190 &Constant::Placeholder => 0,
191 _ => 1
192 }
193 }
194}
195
196#[derive(Debug, PartialEq)]
197pub enum ReferenceKind {
198 GetField = 1,
199 GetStatic = 2,
200 PutField = 3,
201 PutStatic = 4,
202 InvokeVirtual = 5,
203 InvokeStatic = 6,
204 InvokeSpecial = 7,
205 NewInvokeSpecial = 8,
206 InvokeInterface = 9,
207 Unknown = 255
208}
209
210impl ReferenceKind {
211 pub fn from_u8(value: u8) -> ReferenceKind {
212 match value {
213 1 => ReferenceKind::GetField,
214 2 => ReferenceKind::GetStatic,
215 3 => ReferenceKind::PutField,
216 4 => ReferenceKind::PutStatic,
217 5 => ReferenceKind::InvokeVirtual,
218 6 => ReferenceKind::InvokeStatic,
219 7 => ReferenceKind::InvokeSpecial,
220 8 => ReferenceKind::NewInvokeSpecial,
221 9 => ReferenceKind::InvokeInterface,
222 _ => ReferenceKind::Unknown
223 }
224 }
225
226 pub fn to_u8(&self) -> u8 {
227 match *self {
228 ReferenceKind::GetField => 1,
229 ReferenceKind::GetStatic => 2,
230 ReferenceKind::PutField => 3,
231 ReferenceKind::PutStatic => 4,
232 ReferenceKind::InvokeVirtual => 5,
233 ReferenceKind::InvokeStatic => 6,
234 ReferenceKind::InvokeSpecial => 7,
235 ReferenceKind::NewInvokeSpecial => 8,
236 ReferenceKind::InvokeInterface => 9,
237 ReferenceKind::Unknown => 255
238 }
239 }
240}
241
242#[derive(Default, Debug, PartialEq)]
243pub struct AccessFlags {
244 pub flags: u16
245}
246
247impl AccessFlags {
248 pub fn new() -> AccessFlags {
249 AccessFlags::of(0)
250 }
251
252 pub fn of(val: u16) -> AccessFlags {
253 AccessFlags { flags: val }
254 }
255
256 pub fn has_flag(&self, flag: u16) -> bool {
257 self.flags & flag > 0
258 }
259
260 pub fn set_flag(&mut self, flag: u16) {
261 self.flags |= flag;
262 }
263
264 pub fn clear_flag(&mut self, flag: u16) {
265 self.flags &= flag ^ 0xFFFF;
266 }
267}
268
269pub enum ClassAccessFlags {
270 Public = 0x0001, Final = 0x0010, Super = 0x0020, Interface = 0x0200, Abstract = 0x0400, Synthetic = 0x1000, Annotation = 0x2000, Enum = 0x4000 }
279
280pub enum FieldAccessFlags {
281 Public = 0x0001, Private = 0x0002, Protected = 0x0004, Static = 0x0008, Final = 0x0010, Volatile = 0x0040, Transient = 0x0080, Synthetic = 0x1000, Enum = 0x4000 }
291
292pub enum MethodAccessFlags {
293 Public = 0x0001, Private = 0x0002, Protected = 0x0004, Static = 0x0008, Final = 0x0010, Synchronized = 0x0020, Bridge = 0x0040, Varargs = 0x0080, Native = 0x0100, Abstract = 0x0400, Strict = 0x0800, Synthetic = 0x1000 }
306
307pub enum InnerClassAccessFlags {
308 Public = 0x0001, Private = 0x0002, Protected = 0x0004, Static = 0x0008, Final = 0x0010, Interface = 0x0200, Abstract = 0x0400, Synthetic = 0x1000, Annotation = 0x2000, Enum = 0x4000, }
319
320pub enum ParameterAccessFlags {
321 Final = 0x0010,
322 Synthetic = 0x1000,
323 Mandated = 0x8000
324}
325
326#[derive(Default, Debug, PartialEq)]
327pub struct Field {
328 pub access_flags: AccessFlags,
329 pub name_index: ConstantPoolIndex,
330 pub descriptor_index: ConstantPoolIndex,
331 pub attributes: Vec<Attribute>
332}
333
334#[derive(Default, Debug, PartialEq)]
335pub struct Method {
336 pub access_flags: AccessFlags,
337 pub name_index: ConstantPoolIndex,
338 pub descriptor_index: ConstantPoolIndex,
339 pub attributes: Vec<Attribute>
340}
341
342#[derive(Debug, PartialEq)]
343pub enum Attribute {
344 ConstantValue(ConstantPoolIndex),
345 Code { max_stack: u16, max_locals: u16, code: Vec<Instruction>, exception_table: Vec<ExceptionHandler>, attributes: Vec<Attribute> },
346 StackMapTable(Vec<StackMapFrame>),
347 Exceptions(Vec<ConstantPoolIndex>),
348 InnerClasses(Vec<InnerClass>),
349 EnclosingMethod { class_index: ConstantPoolIndex, method_index: ConstantPoolIndex },
350 Synthetic,
351 Signature(ConstantPoolIndex),
352 SourceFile(ConstantPoolIndex),
353 SourceDebugExtension(Vec<u8>),
354 LineNumberTable(Vec<LineNumberTable>),
355 LocalVariableTable(Vec<LocalVariableTable>),
356 LocalVariableTypeTable(Vec<LocalVariableTypeTable>),
357 Deprecated,
358 RuntimeVisibleAnnotations(Vec<Annotation>),
359 RuntimeInvisibleAnnotations(Vec<Annotation>),
360 RuntimeVisibleParameterAnnotations(Vec<Vec<Annotation>>),
361 RuntimeInvisibleParameterAnnotations(Vec<Vec<Annotation>>),
362 RuntimeVisibleTypeAnnotations(Vec<TypeAnnotation>),
363 RuntimeInvisibleTypeAnnotations(Vec<TypeAnnotation>),
364 AnnotationDefault(ElementValue),
365 BootstrapMethods(Vec<BootstrapMethod>),
366 MethodParameters(Vec<MethodParameter>),
367 RawAttribute { name_index: ConstantPoolIndex, info: Vec<u8> }
368}
369
370#[derive(Debug, PartialEq)]
371pub enum StackMapFrame {
372 SameFrame { tag: u8 },
373 SameLocals1StackItemFrame { tag: u8, stack: VerificationType },
374 SameLocals1StackItemFrameExtended { offset_delta: u16, stack: VerificationType },
375 ChopFrame { tag: u8, offset_delta: u16 },
376 SameFrameExtended { offset_delta: u16 },
377 AppendFrame { tag: u8, offset_delta: u16, locals: Vec<VerificationType> },
378 FullFrame { offset_delta: u16, locals: Vec<VerificationType>, stack: Vec<VerificationType> },
379 FutureUse { tag: u8 }
380}
381
382impl StackMapFrame {
383 pub fn len(&self) -> usize {
384 match self {
385 &StackMapFrame::SameFrame { tag: _ } => 1,
386 &StackMapFrame::SameLocals1StackItemFrame{ tag: _, ref stack } => 1 + stack.len(),
387 &StackMapFrame::SameLocals1StackItemFrameExtended { offset_delta: _, ref stack } => 3 + stack.len(),
388 &StackMapFrame::ChopFrame { tag: _, offset_delta: _ } => 3,
389 &StackMapFrame::SameFrameExtended { offset_delta: _ } => 3,
390 &StackMapFrame::AppendFrame { tag: _, offset_delta: _, ref locals } => 3 + locals.iter().fold(0, |acc, x| acc + x.len()),
391 &StackMapFrame::FullFrame { offset_delta: _, ref locals, ref stack } => 7 + locals.iter().fold(0, |acc, x| acc + x.len()) + stack.iter().fold(0, |acc, x| acc + x.len()),
392 &StackMapFrame::FutureUse { tag: _ } => 0
393 }
394 }
395}
396
397#[derive(Debug, PartialEq)]
398pub enum VerificationType {
399 Top,
400 Integer,
401 Float,
402 Long,
403 Double,
404 Null,
405 UninitializedThis,
406 Object { cpool_index: ConstantPoolIndex },
407 Uninitialized { offset: u16 }
408}
409
410impl VerificationType {
411 pub fn len(&self) -> usize {
412 match self {
413 &VerificationType::Object { cpool_index: _ } => 3,
414 &VerificationType::Uninitialized { offset: _ } => 3,
415 _ => 1
416 }
417 }
418}
419
420#[derive(Debug, PartialEq)]
421pub struct ExceptionHandler {
422 pub start_pc: u16,
423 pub end_pc: u16,
424 pub handler_pc: u16,
425 pub catch_type: ConstantPoolIndex
426}
427
428#[derive(Debug, PartialEq)]
429pub struct InnerClass {
430 pub inner_class_info_index: ConstantPoolIndex,
431 pub outer_class_info_index: ConstantPoolIndex,
432 pub inner_name_index: ConstantPoolIndex,
433 pub access_flags: AccessFlags
434}
435
436#[derive(Debug, PartialEq)]
437pub struct LineNumberTable {
438 pub start_pc: u16,
439 pub line_number: u16
440}
441
442#[derive(Debug, PartialEq)]
443pub struct LocalVariableTable {
444 pub start_pc: u16,
445 pub length: u16,
446 pub name_index: ConstantPoolIndex,
447 pub descriptor_index: ConstantPoolIndex,
448 pub index: u16
449}
450
451#[derive(Debug, PartialEq)]
452pub struct LocalVariableTypeTable {
453 pub start_pc: u16,
454 pub length: u16,
455 pub name_index: ConstantPoolIndex,
456 pub signature_index: ConstantPoolIndex,
457 pub index: u16
458}
459
460#[derive(Debug, PartialEq)]
461pub struct Annotation {
462 pub type_index: ConstantPoolIndex,
463 pub element_value_pairs: Vec<ElementValuePair>
464}
465
466impl Annotation {
467 pub fn len(&self) -> usize {
468 4 + self.element_value_pairs.iter().fold(0, |acc, x| acc + x.len())
469 }
471}
472
473#[derive(Debug, PartialEq)]
474pub struct ElementValuePair {
475 pub element_name_index: ConstantPoolIndex,
476 pub value: ElementValue
477}
478
479impl ElementValuePair {
480 pub fn len(&self) -> usize {
481 2 + self.value.len()
482 }
483}
484
485#[derive(Debug, PartialEq)]
486pub enum ElementValue {
487 ConstantValue(u8, ConstantPoolIndex),
488 Enum { type_name_index: ConstantPoolIndex, const_name_index: ConstantPoolIndex },
489 ClassInfo(ConstantPoolIndex),
490 Annotation(Annotation),
491 Array(Vec<ElementValue>)
492}
493
494impl ElementValue {
495 pub fn len(&self) -> usize {
496 match self {
497 &ElementValue::ConstantValue(_, _) => 3,
498 &ElementValue::Enum { type_name_index: _, const_name_index: _ } => 5,
499 &ElementValue::ClassInfo(_) => 3,
500 &ElementValue::Annotation(ref annotation) => 1 + annotation.len(),
501 &ElementValue::Array(ref table) => table.iter().fold(3, |acc, x| acc + x.len())
502 }
503 }
504}
505
506#[derive(Debug, PartialEq)]
507pub struct TypeAnnotation {
508 pub target_info: TargetInfo,
509 pub target_path: TypePath,
510 pub type_index: ConstantPoolIndex,
511 pub element_value_pairs: Vec<ElementValuePair>
512}
513
514impl TypeAnnotation {
515 pub fn len(&self) -> usize {
516 5 + self.target_info.len() + self.target_path.len() + self.element_value_pairs.iter().fold(0, |acc, x| acc + x.len())
517 }
518}
519
520#[derive(Debug, PartialEq)]
521pub enum TargetInfo {
522 TypeParameter { subtype: u8, idx: u8 },
523 SuperType { idx: u16 },
524 TypeParameterBound { subtype: u8, param_idx: u8, bound_index: u8 },
525 Empty { subtype: u8 },
526 MethodFormalParameter { idx: u8 },
527 Throws { idx: u16 },
528 LocalVar { subtype: u8, target: Vec<(u16, u16, u16)> },
529 Catch { idx: u16 },
530 Offset { subtype: u8, idx: u16 },
531 TypeArgument { subtype: u8, offset: u16, type_arg_idx: u8 }
532}
533
534impl TargetInfo {
535 pub fn len(&self) -> usize {
536 match self {
537 &TargetInfo::TypeParameter { subtype: _, idx: _ } => 1,
538 &TargetInfo::SuperType { idx: _ } => 2,
539 &TargetInfo::TypeParameterBound { subtype: _, param_idx: _, bound_index: _ } => 2,
540 &TargetInfo::Empty { subtype: _ } => 0,
541 &TargetInfo::MethodFormalParameter { idx: _ } => 1,
542 &TargetInfo::Throws { idx: _ } => 2,
543 &TargetInfo::LocalVar { subtype: _, ref target } => { 2 + target.len() * 6 },
544 &TargetInfo::Catch { idx: _ } => 2,
545 &TargetInfo::Offset { subtype: _, idx: _ } => 2,
546 &TargetInfo::TypeArgument { subtype: _, offset: _, type_arg_idx: _ } => 3
547 }
548 }
549
550 pub fn subtype(&self) -> u8 {
551 match self {
552 &TargetInfo::TypeParameter { subtype, idx: _ } => subtype,
553 &TargetInfo::SuperType { idx: _ } => 0x10,
554 &TargetInfo::TypeParameterBound { subtype, param_idx: _, bound_index: _ } => subtype,
555 &TargetInfo::Empty { subtype } => subtype,
556 &TargetInfo::MethodFormalParameter { idx: _ } => 0x16,
557 &TargetInfo::Throws { idx: _ } => 0x17,
558 &TargetInfo::LocalVar { subtype, target: _ } => subtype,
559 &TargetInfo::Catch { idx: _ } => 0x42,
560 &TargetInfo::Offset { subtype, idx: _ } => subtype,
561 &TargetInfo::TypeArgument { subtype, offset: _, type_arg_idx: _ } => subtype
562 }
563 }
564}
565
566#[derive(Debug, PartialEq)]
567pub struct TypePath {
568 pub path: Vec<(TypePathKind, u8)>
569}
570
571impl TypePath {
572 pub fn len(&self) -> usize {
573 1 + self.path.len() * 2
574 }
575}
576
577#[derive(Debug, PartialEq)]
578pub enum TypePathKind {
579 Array, Nested, Wildcard, TypeArgument }
584
585impl TypePathKind {
586 pub fn value(&self) -> u8 {
587 match self {
588 &TypePathKind::Array => 0,
589 &TypePathKind::Nested => 1,
590 &TypePathKind::Wildcard => 2,
591 &TypePathKind::TypeArgument => 3,
592 }
593 }
594}
595
596#[derive(Debug, PartialEq)]
597pub struct BootstrapMethod {
598 pub bootstrap_method_ref: ConstantPoolIndex,
599 pub bootstrap_arguments: Vec<ConstantPoolIndex>
600}
601
602impl BootstrapMethod {
603}
604
605#[derive(Debug, PartialEq)]
606pub struct MethodParameter {
607 pub name_index: ConstantPoolIndex,
608 pub access_flags: AccessFlags
609}
610
611impl MethodParameter {
612 pub fn len(&self) -> usize { 4 }
613}
614
615#[allow(non_camel_case_types)]
616#[derive(Debug, PartialEq)]
617pub enum Instruction {
618 AALOAD,
619 AASTORE,
620 ACONST_NULL,
621 ALOAD(u8),
622 ALOAD_0,
623 ALOAD_1,
624 ALOAD_2,
625 ALOAD_3,
626 ANEWARRAY(u16),
627 ARETURN,
628 ARRAYLENGTH,
629 ASTORE(u8),
630 ASTORE_0,
631 ASTORE_1,
632 ASTORE_2,
633 ASTORE_3,
634 ATHROW,
635 BALOAD,
636 BASTORE,
637 BIPUSH(u8),
638 CALOAD,
639 CASTORE,
640 CHECKCAST(u16),
641 D2F,
642 D2I,
643 D2L,
644 DADD,
645 DALOAD,
646 DASTORE,
647 DCMPL,
648 DCMPG,
649 DCONST_0,
650 DCONST_1,
651 DDIV,
652 DLOAD(u8),
653 DLOAD_0,
654 DLOAD_1,
655 DLOAD_2,
656 DLOAD_3,
657 DMUL,
658 DNEG,
659 DREM,
660 DRETURN,
661 DSTORE(u8),
662 DSTORE_0,
663 DSTORE_1,
664 DSTORE_2,
665 DSTORE_3,
666 DSUB,
667 DUP,
668 DUP_X1,
669 DUP_X2,
670 DUP2,
671 DUP2_X1,
672 DUP2_X2,
673 F2D,
674 F2I,
675 F2L,
676 FADD,
677 FALOAD,
678 FASTORE,
679 FCMPL,
680 FCMPG,
681 FCONST_0,
682 FCONST_1,
683 FCONST_2,
684 FDIV,
685 FLOAD(u8),
686 FLOAD_0,
687 FLOAD_1,
688 FLOAD_2,
689 FLOAD_3,
690 FMUL,
691 FNEG,
692 FREM,
693 FRETURN,
694 FSTORE(u8),
695 FSTORE_0,
696 FSTORE_1,
697 FSTORE_2,
698 FSTORE_3,
699 FSUB,
700 GETFIELD(u16),
701 GETSTATIC(u16),
702 GOTO(i16),
703 GOTO_W(i32),
704 I2B,
705 I2C,
706 I2D,
707 I2F,
708 I2L,
709 I2S,
710 IADD,
711 IALOAD,
712 IAND,
713 IASTORE,
714 ICONST_M1,
715 ICONST_0,
716 ICONST_1,
717 ICONST_2,
718 ICONST_3,
719 ICONST_4,
720 ICONST_5,
721 IDIV,
722 IF_ACMPEQ(i16),
723 IF_ACMPNE(i16),
724 IF_ICMPEQ(i16),
725 IF_ICMPNE(i16),
726 IF_ICMPLT(i16),
727 IF_ICMPGE(i16),
728 IF_ICMPGT(i16),
729 IF_ICMPLE(i16),
730 IFEQ(i16),
731 IFNE(i16),
732 IFLT(i16),
733 IFGE(i16),
734 IFGT(i16),
735 IFLE(i16),
736 IFNONNULL(i16),
737 IFNULL(i16),
738 IINC(u8, i8),
739 ILOAD(u8),
740 ILOAD_0,
741 ILOAD_1,
742 ILOAD_2,
743 ILOAD_3,
744 IMUL,
745 INEG,
746 INSTANCEOF(u16),
747 INVOKEDYNAMIC(u16),
748 INVOKEINTERFACE(u16, u8),
749 INVOKESPECIAL(u16),
750 INVOKESTATIC(u16),
751 INVOKEVIRTUAL(u16),
752 IOR,
753 IREM,
754 IRETURN,
755 ISHL,
756 ISHR,
757 ISTORE(u8),
758 ISTORE_0,
759 ISTORE_1,
760 ISTORE_2,
761 ISTORE_3,
762 ISUB,
763 IUSHR,
764 IXOR,
765 JSR(i16),
766 JSR_W(i32),
767 L2D,
768 L2F,
769 L2I,
770 LADD,
771 LALOAD,
772 LAND,
773 LASTORE,
774 LCMP,
775 LCONST_0,
776 LCONST_1,
777 LDC(u8),
778 LDC_W(u16),
779 LDC2_W(u16),
780 LDIV,
781 LLOAD(u8),
782 LLOAD_0,
783 LLOAD_1,
784 LLOAD_2,
785 LLOAD_3,
786 LMUL,
787 LNEG,
788 LOOKUPSWITCH(i32, Vec<(i32, i32)>),
789 LOR,
790 LREM,
791 LRETURN,
792 LSHL,
793 LSHR,
794 LSTORE(u8),
795 LSTORE_0,
796 LSTORE_1,
797 LSTORE_2,
798 LSTORE_3,
799 LSUB,
800 LUSHR,
801 LXOR,
802 MONITORENTER,
803 MONITOREXIT,
804 MULTIANEWARRAY(u16, u8),
805 NEW(u16),
806 NEWARRAY(u8),
807 NOP,
808 POP,
809 POP2,
810 PUTFIELD(u16),
811 PUTSTATIC(u16),
812 RET(u8),
813 RETURN,
814 SALOAD,
815 SASTORE,
816 SIPUSH(u16),
817 SWAP,
818 TABLESWITCH(i32, i32, i32, Vec<i32>),
819 IINC_W(u16, i16),
820 ILOAD_W(u16),
821 FLOAD_W(u16),
822 ALOAD_W(u16),
823 LLOAD_W(u16),
824 DLOAD_W(u16),
825 ISTORE_W(u16),
826 FSTORE_W(u16),
827 ASTORE_W(u16),
828 LSTORE_W(u16),
829 DSTORE_W(u16),
830 RET_W(u16),
831 PADDED_INSTRUCTION(usize),
832 WTF(u32),
833}
834
835impl Instruction {
836 pub fn len(&self) -> usize {
837 match self {
838 &Instruction::ALOAD(_) => 2,
839 &Instruction::ANEWARRAY(_) => 3,
840 &Instruction::ASTORE(_) => 2,
841 &Instruction::BIPUSH(_) => 2,
842 &Instruction::CHECKCAST(_) => 3,
843 &Instruction::DLOAD(_) => 2,
844 &Instruction::DSTORE(_) => 2,
845 &Instruction::FLOAD(_) => 2,
846 &Instruction::FSTORE(_) => 2,
847 &Instruction::GETFIELD(_) => 3,
848 &Instruction::GETSTATIC(_) => 3,
849 &Instruction::GOTO(_) => 3,
850 &Instruction::GOTO_W(_) => 5,
851 &Instruction::IF_ACMPEQ(_) => 3,
852 &Instruction::IF_ACMPNE(_) => 3,
853 &Instruction::IF_ICMPEQ(_) => 3,
854 &Instruction::IF_ICMPNE(_) => 3,
855 &Instruction::IF_ICMPLT(_) => 3,
856 &Instruction::IF_ICMPGE(_) => 3,
857 &Instruction::IF_ICMPGT(_) => 3,
858 &Instruction::IF_ICMPLE(_) => 3,
859 &Instruction::IFEQ(_) => 3,
860 &Instruction::IFNE(_) => 3,
861 &Instruction::IFLT(_) => 3,
862 &Instruction::IFGE(_) => 3,
863 &Instruction::IFGT(_) => 3,
864 &Instruction::IFLE(_) => 3,
865 &Instruction::IFNONNULL(_) => 3,
866 &Instruction::IFNULL(_) => 3,
867 &Instruction::IINC(_, _) => 3,
868 &Instruction::ILOAD(_) => 2,
869 &Instruction::INSTANCEOF(_) => 3,
870 &Instruction::INVOKEDYNAMIC(_) => 5,
871 &Instruction::INVOKEINTERFACE(_, _) => 5,
872 &Instruction::INVOKESPECIAL(_) => 3,
873 &Instruction::INVOKESTATIC(_) => 3,
874 &Instruction::INVOKEVIRTUAL(_) => 3,
875 &Instruction::ISTORE(_) => 2,
876 &Instruction::JSR(_) => 3,
877 &Instruction::JSR_W(_) => 5,
878 &Instruction::LDC(_) => 2,
879 &Instruction::LDC_W(_) => 3,
880 &Instruction::LDC2_W(_) => 3,
881 &Instruction::LLOAD(_) => 2,
882 &Instruction::LOOKUPSWITCH(_, ref pairs) => { 5 + pairs.len() * 4 },
883 &Instruction::LSTORE(_) => 2,
884 &Instruction::MULTIANEWARRAY(_, _) => 4,
885 &Instruction::NEW(_) => 3,
886 &Instruction::NEWARRAY(_) => 2,
887 &Instruction::PUTFIELD(_) => 3,
888 &Instruction::PUTSTATIC(_) => 3,
889 &Instruction::RET(_) => 2,
890 &Instruction::SIPUSH(_) => 3,
891 &Instruction::TABLESWITCH(_, _, _, ref indices) => { 13 + (indices.len() * 4) },
892 &Instruction::IINC_W(_, _) => 9,
893 &Instruction::ILOAD_W(_) => 5,
894 &Instruction::FLOAD_W(_) => 5,
895 &Instruction::ALOAD_W(_) => 5,
896 &Instruction::LLOAD_W(_) => 5,
897 &Instruction::DLOAD_W(_) => 5,
898 &Instruction::ISTORE_W(_) => 5,
899 &Instruction::FSTORE_W(_) => 5,
900 &Instruction::ASTORE_W(_) => 5,
901 &Instruction::LSTORE_W(_) => 5,
902 &Instruction::DSTORE_W(_) => 5,
903 &Instruction::RET_W(_) => 5,
904 &Instruction::PADDED_INSTRUCTION(padding) => padding,
905 _ => 1
906 }
907 }
908}