jvmti/bytecode/
classfile.rs

1
2///
3/// A `Classfile` represents a definition of a single JVM class or interface. Unlike the bytecode
4/// itself, it doesn't represent every byte in the class definition, though, many information are
5/// encoded in the type system instead. This approach may seem restrictive but it helps achieving
6/// bytecode safety.
7#[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    /// Create a new classfile, initialised with sensible default values
22    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///
44/// Describe a classfile version number.
45#[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///
67/// A `ConstantPool` is a table of various string and number literal constants that are referred
68/// within the substructures of the `Classfile`.
69#[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.iter().fold(0, |acc, x| acc + x.cp_size())
142        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, // Declared public; may be accessed from outside its package.
271    Final = 0x0010, // Declared final; no subclasses allowed.
272    Super = 0x0020, // Treat superclass methods specially when invoked by the invokespecial instruction.
273    Interface = 0x0200, // Is an interface, not a class.
274    Abstract = 0x0400, // Declared abstract; must not be instantiated.
275    Synthetic = 0x1000, // Declared synthetic; not present in the source code.
276    Annotation = 0x2000, // Declared as an annotation type.
277    Enum = 0x4000 // Declared as an enum type.
278}
279
280pub enum FieldAccessFlags {
281    Public = 0x0001, //	Declared public; may be accessed from outside its package.
282    Private = 0x0002, //	Declared private; usable only within the defining class.
283    Protected = 0x0004, //	Declared protected; may be accessed within subclasses.
284    Static = 0x0008, //	Declared static.
285    Final = 0x0010, //	Declared final; never directly assigned to after object construction (JLS §17.5).
286    Volatile = 0x0040, //	Declared volatile; cannot be cached.
287    Transient = 0x0080, //	Declared transient; not written or read by a persistent object manager.
288    Synthetic = 0x1000, //	Declared synthetic; not present in the source code.
289    Enum = 0x4000 //	Declared as an element of an enum.
290}
291
292pub enum MethodAccessFlags {
293    Public = 0x0001, //	Declared public; may be accessed from outside its package.
294    Private = 0x0002, //	Declared private; accessible only within the defining class.
295    Protected = 0x0004, //	Declared protected; may be accessed within subclasses.
296    Static = 0x0008, //	Declared static.
297    Final = 0x0010, //	Declared final; must not be overridden (§5.4.5).
298    Synchronized = 0x0020, //	Declared synchronized; invocation is wrapped by a monitor use.
299    Bridge = 0x0040, //	A bridge method, generated by the compiler.
300    Varargs = 0x0080, //	Declared with variable number of arguments.
301    Native = 0x0100, //	Declared native; implemented in a language other than Java.
302    Abstract = 0x0400, //	Declared abstract; no implementation is provided.
303    Strict = 0x0800, //	Declared strictfp; floating-point mode is FP-strict.
304    Synthetic = 0x1000 //	Declared synthetic; not present in the source code.
305}
306
307pub enum InnerClassAccessFlags {
308    Public = 0x0001, //	Marked or implicitly public in source.
309    Private = 0x0002, //	Marked private in source.
310    Protected = 0x0004, //	Marked protected in source.
311    Static = 0x0008, //	Marked or implicitly static in source.
312    Final = 0x0010, //	Marked final in source.
313    Interface = 0x0200, //	Was an interface in source.
314    Abstract = 0x0400, //	Marked or implicitly abstract in source.
315    Synthetic = 0x1000, //	Declared synthetic; not present in the source code.
316    Annotation = 0x2000, //	Declared as an annotation type.
317    Enum = 0x4000, //	Declared as an enum type.
318}
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        //4 + self.element_value_pairs.len() * 2 + self.element_value_pairs.iter().fold(0, |acc, x| acc + x.len())
470    }
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, // Annotation is deeper in an array type
580    Nested, // Annotation is deeper in a nested type
581    Wildcard, // Annotation is on the bound of a wildcard type argument of a parameterized type
582    TypeArgument // Annotation is on a type argument of a parameterized type
583}
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}