jbcrs_basic/
tree.rs

1//! The tree package provides the basic structure of a basic class file
2
3use std::collections::BTreeMap;
4
5/// The first 4 bytes of every java class file
6pub const MAGIC: &[u8] = &[0xCA, 0xFE, 0xBA, 0xBE];
7
8/// A java class file.
9#[derive(Debug)]
10pub struct Class {
11    pub minor_version: u16,
12    pub major_version: u16,
13
14    pub access_flags: AccessFlags,
15    pub name: u16,
16    pub super_name: u16,
17    pub interfaces: Vec<u16>,
18
19    pub fields: Vec<Field>,
20    pub methods: Vec<Method>,
21
22    pub attributes: Vec<Attribute>,
23}
24
25/// A field.
26#[derive(Debug)]
27pub struct Field {
28    pub access_flags: AccessFlags,
29    pub name: u16,
30    pub desc: u16,
31    pub attributes: Vec<Attribute>,
32}
33
34/// A method.
35#[derive(Debug)]
36pub struct Method {
37    pub access_flags: AccessFlags,
38    pub name: u16,
39    pub desc: u16,
40    pub attributes: Vec<Attribute>,
41}
42
43/// An Attribute.
44#[derive(Debug)]
45pub enum Attribute {
46    AnnotationDefault(ElementValue),
47    BootstrapMethods(Vec<BootstrapMethod>),
48    Code {
49        max_stack: u16,
50        max_locals: u16,
51        instructions: Vec<Option<Instruction>>,
52        exceptions: Vec<Exception>,
53        attributes: Vec<Attribute>,
54    },
55    ConstantValue(u16),
56    Deprecated,
57    EnclosingMethod {
58        class_index: u16,
59        method_index: u16,
60    },
61    Exceptions(Vec<u16>),
62    InnerClasses(Vec<InnerClass>),
63    LineNumberTable(Vec<LineNumber>),
64    LocalVariableTable(Vec<LocalVariable>),
65    LocalVariableTypeTable(Vec<LocalVariableType>),
66    MethodParameters(Vec<MethodParameter>),
67    Module {
68        name: u16,
69        flags: AccessFlags,
70        version: u16,
71
72        requires: Vec<Requirement>,
73        exports: Vec<Export>,
74        opens: Vec<Opening>,
75        uses: Vec<u16>,
76        provides: Vec<Provider>,
77    },
78    ModuleMainClass(u16),
79    ModulePackages(Vec<u16>),
80    RuntimeVisibleAnnotations(Vec<Annotation>),
81    RuntimeInvisibleAnnotations(Vec<Annotation>),
82    RuntimeVisibleParameterAnnotations(Vec<Vec<Annotation>>),
83    RuntimeInvisibleParameterAnnotations(Vec<Vec<Annotation>>),
84    RuntimeVisibleTypeAnnotations(Vec<TypeAnnotation>),
85    RuntimeInvisibleTypeAnnotations(Vec<TypeAnnotation>),
86    Signature(u16),
87    Synthetic,
88    SourceFile(u16),
89    SourceDebugExtension(String),
90    StackMapTable(Vec<StackMapFrame>),
91    Unknown(u16, Vec<u8>),
92}
93
94bitflags! {
95    /// The access flags of a part of the class
96    pub struct AccessFlags: u16 {
97        const PUBLIC       = 0b0000_0000_0000_0001;
98        const PRIVATE      = 0b0000_0000_0000_0010;
99        const PROTECTED    = 0b0000_0000_0000_0100;
100        const STATIC       = 0b0000_0000_0000_1000;
101        const FINAL        = 0b0000_0000_0001_0000;
102        const SUPER        = 0b0000_0000_0010_0000;
103        const SYNCHRONIZED = 0b0000_0000_0010_0000;
104        const VOLATILE     = 0b0000_0000_0100_0000;
105        const BRIDGE       = 0b0000_0000_0100_0000;
106        const STATIC_PHASE = 0b0000_0000_0100_0000;
107        const TRANSIENT    = 0b0000_0000_1000_0000;
108        const VARARGS      = 0b0000_0000_1000_0000;
109        const NATIVE       = 0b0000_0001_0000_0000;
110        const INTERFACE    = 0b0000_0010_0000_0000;
111        const ABSTRACT     = 0b0000_0100_0000_0000;
112        const STRICT       = 0b0000_1000_0000_0000;
113        const SYNTHETIC    = 0b0001_0000_0000_0000;
114        const ANNOTATION   = 0b0010_0000_0000_0000;
115        const ENUM         = 0b0100_0000_0000_0000;
116        const MODULE       = 0b1000_0000_0000_0001;
117        const MANDATED     = 0b1000_0000_0000_0001;
118    }
119}
120
121#[derive(Debug)]
122pub struct Exception {
123    pub start: u16,
124    pub end: u16,
125    pub handler: u16,
126    pub catch_type: u16,
127}
128
129#[derive(Debug)]
130pub struct BootstrapMethod {
131    pub method_ref: u16,
132    pub arguments: Vec<u16>,
133}
134
135#[derive(Debug)]
136pub struct LineNumber {
137    pub start: u16,
138    pub line_number: u16,
139}
140
141#[derive(Debug)]
142pub enum Instruction {
143    /// No operation
144    NOP,
145
146    /// Pushes null on the stack
147    AConstNull,
148
149    /// Pushes the int -1 on the stack
150    IConstM1,
151
152    /// Pushes the int 0 on the stack
153    IConst0,
154    /// Pushes the int 1 on the stack
155    IConst1,
156    /// Pushes the int 2 on the stack
157    IConst2,
158    /// Pushes the int 3 on the stack
159    IConst3,
160    /// Pushes the int 4 on the stack
161    IConst4,
162    /// Pushes the int 5 on the stack
163    IConst5,
164
165    /// Pushes the long 0 on the stack
166    LConst0,
167    /// Pushes the long 1 on the stack
168    LConst1,
169
170    /// Pushes the float 0 on the stack
171    FConst0,
172    /// Pushes the float 1 on the stack
173    FConst1,
174    /// Pushes the float 2 on the stack
175    FConst2,
176
177    /// Pushes the double 0 on the stack
178    DConst0,
179    /// Pushes the double 1 on the stack
180    DConst1,
181
182    /// Pushes a byte on the stack
183    BIPush(i8),
184    /// Pushes a short on the stack
185    SIPush(i16),
186
187    /// Pushes a constant from the constant pool on the stack
188    LDC(u16),
189
190    /// Pushes the int at a specific local variable index on the stack
191    ILoad(u16),
192    /// Pushes the long at a specific local variable index on the stack
193    LLoad(u16),
194    /// Pushes the float at a specific local variable index on the stack
195    FLoad(u16),
196    /// Pushes the double at a specific local variable index on the stack
197    DLoad(u16),
198    /// Pushes the reference at a specific local variable index on the stack
199    ALoad(u16),
200
201    /// Pushes the int at local variable index 0 on the stack
202    ILoad0,
203    /// Pushes the int at local variable index 1 on the stack
204    ILoad1,
205    /// Pushes the int at local variable index 2 on the stack
206    ILoad2,
207    /// Pushes the int at local variable index 3 on the stack
208    ILoad3,
209
210    /// Pushes the long at local variable index 0 on the stack
211    LLoad0,
212    /// Pushes the long at local variable index 1 on the stack
213    LLoad1,
214    /// Pushes the long at local variable index 2 on the stack
215    LLoad2,
216    /// Pushes the long at local variable index 3 on the stack
217    LLoad3,
218
219    /// Pushes the float at local variable index 0 on the stack
220    FLoad0,
221    /// Pushes the float at local variable index 1 on the stack
222    FLoad1,
223    /// Pushes the float at local variable index 2 on the stack
224    FLoad2,
225    /// Pushes the float at local variable index 3 on the stack
226    FLoad3,
227
228    /// Pushes the double at local variable index 0 on the stack
229    DLoad0,
230    /// Pushes the double at local variable index 1 on the stack
231    DLoad1,
232    /// Pushes the double at local variable index 2 on the stack
233    DLoad2,
234    /// Pushes the double at local variable index 3 on the stack
235    DLoad3,
236
237    /// Pushes the reference at local variable index 0 on the stack
238    ALoad0,
239    /// Pushes the reference at local variable index 1 on the stack
240    ALoad1,
241    /// Pushes the reference at local variable index 2 on the stack
242    ALoad2,
243    /// Pushes the reference at local variable index 3 on the stack
244    ALoad3,
245
246    /// Pushes the value from an int array, which is popped from the stack,
247    /// at an index, which is popped from the stack as well, on the stack.
248    IALoad,
249    /// Pushes the value from an long array, which is popped from the stack,
250    /// at an index, which is popped from the stack as well, on the stack.
251    LALoad,
252    /// Pushes the value from an float array, which is popped from the stack,
253    /// at an index, which is popped from the stack as well, on the stack.
254    FALoad,
255    /// Pushes the value from an double array, which is popped from the stack,
256    /// at an index, which is popped from the stack as well, on the stack.
257    DALoad,
258    /// Pushes the value from an reference array, which is popped from the stack,
259    /// at an index, which is popped from the stack as well, on the stack.
260    AALoad,
261    /// Pushes the value from an byte array, which is popped from the stack,
262    /// at an index, which is popped from the stack as well, on the stack.
263    BALoad,
264    /// Pushes the value from an char array, which is popped from the stack,
265    /// at an index, which is popped from the stack as well, on the stack.
266    CALoad,
267    /// Pushes the value from an short array, which is popped from the stack,
268    /// at an index, which is popped from the stack as well, on the stack.
269    SALoad,
270
271    IStore(u16),
272    LStore(u16),
273    FStore(u16),
274    DStore(u16),
275    AStore(u16),
276
277    IStore0,
278    IStore1,
279    IStore2,
280    IStore3,
281
282    LStore0,
283    LStore1,
284    LStore2,
285    LStore3,
286
287    FStore0,
288    FStore1,
289    FStore2,
290    FStore3,
291
292    DStore0,
293    DStore1,
294    DStore2,
295    DStore3,
296
297    AStore0,
298    AStore1,
299    AStore2,
300    AStore3,
301
302    IAStore,
303    LAStore,
304    FAStore,
305    DAStore,
306    AAStore,
307    BAStore,
308    CAStore,
309    SAStore,
310
311    Pop,
312    Pop2,
313
314    Dup,
315    DupX1,
316    DupX2,
317
318    Dup2,
319    Dup2X1,
320    Dup2X2,
321
322    Swap,
323
324    IAdd,
325    LAdd,
326    FAdd,
327    DAdd,
328
329    ISub,
330    LSub,
331    FSub,
332    DSub,
333
334    IMul,
335    LMul,
336    FMul,
337    DMul,
338
339    IDiv,
340    LDiv,
341    FDiv,
342    DDiv,
343
344    IRem,
345    LRem,
346    FRem,
347    DRem,
348
349    INeg,
350    LNeg,
351    FNeg,
352    DNeg,
353
354    IShL,
355    LShL,
356
357    IShR,
358    LShR,
359
360    IUShR,
361    LUShR,
362
363    IAnd,
364    LAnd,
365
366    IOr,
367    LOr,
368
369    IXOr,
370    LXOr,
371
372    IInc(u16, i16),
373
374    I2L,
375    I2F,
376    I2D,
377
378    L2I,
379    L2F,
380    L2D,
381
382    F2I,
383    F2L,
384    F2D,
385
386    D2I,
387    D2L,
388    D2F,
389
390    I2B,
391    I2C,
392    I2S,
393
394    LCmp,
395
396    FCmpL,
397    FCmpG,
398
399    DCmpL,
400    DCmpG,
401
402    IfEq(i16),
403    IfNE(i16),
404    IfLT(i16),
405    IfGE(i16),
406    IfGT(i16),
407    IfLE(i16),
408
409    IfICmpEq(i16),
410    IfICmpNE(i16),
411    IfICmpLT(i16),
412    IfICmpGE(i16),
413    IfICmpGT(i16),
414    IfICmpLE(i16),
415
416    IfACmpEq(i16),
417    IfACmpNE(i16),
418
419    GoTo(i32),
420    JSR(i32),
421    Ret(u16),
422
423    TableSwitch {
424        default: i32,
425        low: i32,
426        high: i32,
427        offsets: Vec<i32>,
428    },
429    LookupSwitch {
430        default: i32,
431        offsets: BTreeMap<i32, i32>,
432    },
433
434    IReturn,
435    LReturn,
436    FReturn,
437    DReturn,
438    AReturn,
439    Return,
440
441    GetStatic(u16),
442    PutStatic(u16),
443    GetField(u16),
444    PutField(u16),
445
446    InvokeVirtual(u16),
447    InvokeSpecial(u16),
448    InvokeStatic(u16),
449    InvokeInterface(u16, u8),
450    InvokeDynamic(u16),
451
452    New(u16),
453    NewArray(ArrayType),
454    ANewArray(u16),
455    ArrayLength,
456
457    AThrow,
458
459    CheckCast(u16),
460    InstanceOf(u16),
461
462    MonitorEnter,
463    MonitorExit,
464
465    MultiANewArray(u16, u8),
466
467    IfNull(i16),
468    IfNonNull(i16),
469
470    BreakPoint,
471    ImpDep1,
472    ImpDep2,
473}
474
475#[derive(Debug)]
476pub enum ArrayType {
477    Boolean,
478    Char,
479    Float,
480    Double,
481    Byte,
482    Short,
483    Int,
484    Long,
485}
486
487#[derive(Debug)]
488pub struct InnerClass {
489    pub inner_class_info: u16,
490    pub outer_class_info: u16,
491    pub inner_name: u16,
492    pub inner_class_access_flags: AccessFlags,
493}
494
495#[derive(Debug)]
496pub enum StackMapFrame {
497    Same {
498        offset_delta: u16,
499    },
500    Same1 {
501        offset_delta: u16,
502        stack: VerificationType,
503    },
504    Chop {
505        offset_delta: u16,
506        count: u8,
507    },
508    Append {
509        offset_delta: u16,
510        locals: Vec<VerificationType>,
511    },
512    Full {
513        offset_delta: u16,
514        locals: Vec<VerificationType>,
515        stack: Vec<VerificationType>,
516    },
517}
518
519#[derive(Debug)]
520pub enum VerificationType {
521    Top,
522    Integer,
523    Float,
524    Double,
525    Long,
526    Null,
527    UninitializedThis,
528    Object(u16),
529    Uninitialized(u16),
530}
531
532#[derive(Debug)]
533pub struct Annotation {
534    /// Must be an index to the constant pool with an `Item::UTF8(_)`
535    /// representing a field descriptor
536    pub type_index: u16,
537    /// The value every single pair holds.
538    /// The first part is an index to the constant pool,
539    /// which must be an `Item::UTF8(_)`.
540    /// The second one is the value itself.
541    pub element_value_pairs: Vec<(u16, ElementValue)>,
542}
543
544#[derive(Debug)]
545pub enum ElementValue {
546    /// The index to the constant pool
547    /// which must be an `Item::Integer(_)`.
548    Byte(u16),
549    /// The index to the constant pool
550    /// which must be an `Item::Integer(_)`.
551    Short(u16),
552    /// The index to the constant pool
553    /// which must be an `Item::Integer(_)`.
554    Char(u16),
555    /// The index to the constant pool
556    /// which must be an `Item::Integer(_)`.
557    Int(u16),
558    /// The index to the constant pool
559    /// which must be an `Item::Long(_)`.
560    Long(u16),
561    /// The index to the constant pool
562    /// which must be an `Item::Float(_)`.
563    Float(u16),
564    /// The index to the constant pool
565    /// which must be an `Item::Double(_)`.
566    Double(u16),
567    /// The index to the constant pool
568    /// which must be an `Item::Integer(_)`.
569    /// Yes, it really needs a constant pool entry for this.
570    Boolean(u16),
571    /// The index to the constant pool
572    /// which must be an `Item::UTF8(_)`.
573    String(u16),
574    /// An enum constant.
575    Enum {
576        /// The index to the constant pool,
577        /// which must be an `Item::UTF8(_)`.
578        /// It results in the internal form of the binary name
579        /// of the type of this enum constant.
580        type_name: u16,
581        /// The index to the constant pool,
582        /// which must be an `Item::UTF8(_)`.
583        /// It results in the simple name
584        /// of this enum constant.
585        const_name: u16,
586    },
587    /// A class literal.
588    /// The index to the constant pool
589    /// which must be an `Item::UTF8(_)`
590    /// representing a return descriptor.
591    Class(u16),
592    /// Another annotation.
593    Annotation(Box<Annotation>),
594    /// Multiple `ElementValue`s
595    Array(Vec<ElementValue>),
596}
597
598#[derive(Debug)]
599pub struct TypeAnnotation {
600    pub target_type: TargetType,
601    pub target_path: Vec<TypePathElement>,
602    pub annotation: Annotation,
603}
604
605#[derive(Debug)]
606pub enum TargetType {
607    /// Indicates that an annotation is present
608    /// on the type parameter of a class.
609    /// The index of the type parameter.
610    TypeParameterClass(u8),
611    /// Indicates that an annotation is present
612    /// on the type parameter of a method.
613    /// The index of the type parameter.
614    TypeParameterMethod(u8),
615    /// Indicates that an annotation is present
616    /// on the implements or extends clause of a class.
617    /// The index of the super type,
618    /// 0xFFFF is the extends clause.
619    SuperType(u16),
620    /// Indicates that an annotation is present
621    /// on a bound of a type parameter of a class.
622    TypeParameterBoundClass {
623        /// The index of the type parameter.
624        type_parameter: u8,
625        /// The index of the bound.
626        bound_index: u8,
627    },
628    /// Indicates that an annotation is present
629    /// on a bound of a type parameter of a method.
630    TypeParameterBoundMethod {
631        /// The index of the type parameter.
632        type_parameter: u8,
633        /// The index of the bound.
634        bound_index: u8,
635    },
636    /// Indicates that an annotation is present
637    /// on the type of a field declaration.
638    EmptyField,
639    /// Indicates that an annotation is present
640    /// on the return type of a method
641    /// or the type of a newly constructed object.
642    EmptyReturn,
643    /// Indicates that an annotation is present
644    /// on the receiver type of a method.
645    EmptyReceiver,
646    /// Indicates that an annotation is present
647    /// on the type in a formal parameter declaration.
648    /// The index of the formal parameter.
649    FormalParameter(u8),
650    /// Indicates that an annotation is present
651    /// on the type in a throws clause.
652    /// The index into the table of the `Exceptions` attribute of the method.
653    Throws(u16),
654    /// Indicates that an annotation is present
655    /// on the type in a local variable declaration.
656    LocalVariable(Vec<LocalVariableTarget>),
657    /// Indicates that an annotation is present
658    /// on the type in a local variable declaration.
659    ResourceVariable(Vec<LocalVariableTarget>),
660    /// Indicates that an annotation is present
661    /// on the type in an exception parameter declaration.
662    Catch(u16),
663    /// Indicates that an annotation is present
664    /// on the type in an instanceof expression.
665    OffsetInstanceOf(u16),
666    /// Indicates that an annotation is present
667    /// on the type in a new expression.
668    OffsetNew(u16),
669    /// Indicates that an annotation is present
670    /// on the type before the ::new
671    /// of a method reference expression.
672    OffsetNewRef(u16),
673    /// Indicates that an annotation is present
674    /// on the type before the ::name
675    /// of a method reference expression.
676    OffsetRef(u16),
677    /// Indicates that an annotation is present
678    /// on the type of a cast expression.
679    TypeArgumentCast { offset: u16, type_argument: u8 },
680    /// Indicates that an annotation is present
681    /// on the type of a method call expression.
682    TypeArgumentMethod { offset: u16, type_argument: u8 },
683    /// Indicates that an annotation is present
684    /// on the type of a new expression.
685    TypeArgumentConstructor { offset: u16, type_argument: u8 },
686    /// Indicates that an annotation is present
687    /// on the type of a ::new expression.
688    TypeArgumentNewRef { offset: u16, type_argument: u8 },
689    /// Indicates that an annotation is present
690    /// on the type of a ::name expression.
691    TypeArgumentRef { offset: u16, type_argument: u8 },
692}
693
694#[derive(Debug)]
695pub struct TypePathElement {
696    pub path_kind: TypePathKind,
697    pub argument_index: u8,
698}
699
700#[derive(Debug)]
701pub enum TypePathKind {
702    /// Annotation is deeper in an array kind
703    ArrayType,
704    /// Annotation is deeper in a nested type
705    NestedType,
706    /// Annotation is on the bound of a wildcard type argument of a parameterized type
707    WildcardType,
708    /// Annotation is on a type argument of a parameterized type
709    Type,
710}
711
712#[derive(Debug)]
713pub struct LocalVariableTarget {
714    /// Start of the Code.
715    pub start: u16,
716    /// Length of the Code.
717    pub length: u16,
718    /// The index in the local variable array of the current frame.
719    /// double and long do occupy two spaces.
720    pub index: u16,
721}
722
723/// An entry of the `LocalVariableTable`
724#[derive(Debug)]
725pub struct LocalVariable {
726    /// Start of the Code.
727    pub start: u16,
728    /// Length of the Code.
729    pub length: u16,
730    /// The index to an `Item::UTF8(_)` representing a valid unqalified name.
731    pub name: u16,
732    /// The index to an `Item::UTF8(_)` representing a field/type descriptor.
733    pub descriptor: u16,
734    /// The index in the local variable array of the current frame.
735    /// double and long do occupy two spaces.
736    pub index: u16,
737}
738
739/// An entry of the `LocalVariableTypeTable`
740#[derive(Debug)]
741pub struct LocalVariableType {
742    /// Start of the Code.
743    pub start: u16,
744    /// Length of the Code.
745    pub length: u16,
746    /// The index to an `Item::UTF8(_)` representing a valid unqalified name.
747    pub name: u16,
748    /// The index to an `Item::UTF8(_)` representing a field signature.
749    pub signature: u16,
750    /// The index in the local variable array of the current frame.
751    /// double and long do occupy two spaces.
752    pub index: u16,
753}
754
755#[derive(Debug)]
756pub struct MethodParameter {
757    pub name: u16,
758    pub access_flags: AccessFlags,
759}
760
761#[derive(Debug)]
762pub struct Requirement {
763    pub index: u16,
764    pub flags: AccessFlags,
765    pub version: u16,
766}
767
768#[derive(Debug)]
769pub struct Export {
770    pub index: u16,
771    pub flags: AccessFlags,
772    pub to: Vec<u16>,
773}
774
775#[derive(Debug)]
776pub struct Opening {
777    pub index: u16,
778    pub flags: AccessFlags,
779    pub to: Vec<u16>,
780}
781
782#[derive(Debug)]
783pub struct Provider {
784    pub index: u16,
785    pub with: Vec<u16>,
786}