Skip to main content

java_class_rs/
types.rs

1use bitflags::bitflags;
2
3/// Parsed Java class file.
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5#[derive(Debug, Clone)]
6pub struct ClassFile {
7    pub minor_version: u16,
8    pub major_version: u16,
9    pub constant_pool: Vec<ConstantPoolEntry>,
10    pub access_flags: ClassAccessFlags,
11    pub this_class: u16,
12    pub super_class: u16,
13    pub interfaces: Vec<u16>,
14    pub fields: Vec<FieldInfo>,
15    pub methods: Vec<MethodInfo>,
16    pub attributes: Vec<AttributeInfo>,
17}
18
19bitflags! {
20    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22    pub struct ClassAccessFlags: u16 {
23        const PUBLIC = 0x0001;
24        const FINAL = 0x0010;
25        const SUPER = 0x0020;
26        const INTERFACE = 0x0200;
27        const ABSTRACT = 0x0400;
28        const SYNTHETIC = 0x1000;
29        const ANNOTATION = 0x2000;
30        const ENUM = 0x4000;
31        const MODULE = 0x8000;
32    }
33}
34
35bitflags! {
36    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
37    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
38    pub struct FieldAccessFlags: u16 {
39        const PUBLIC = 0x0001;
40        const PRIVATE = 0x0002;
41        const PROTECTED = 0x0004;
42        const STATIC = 0x0008;
43        const FINAL = 0x0010;
44        const VOLATILE = 0x0040;
45        const TRANSIENT = 0x0080;
46        const SYNTHETIC = 0x1000;
47        const ENUM = 0x4000;
48    }
49}
50
51bitflags! {
52    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
54    pub struct MethodAccessFlags: u16 {
55        const PUBLIC = 0x0001;
56        const PRIVATE = 0x0002;
57        const PROTECTED = 0x0004;
58        const STATIC = 0x0008;
59        const FINAL = 0x0010;
60        const SYNCHRONIZED = 0x0020;
61        const BRIDGE = 0x0040;
62        const VARARGS = 0x0080;
63        const NATIVE = 0x0100;
64        const ABSTRACT = 0x0400;
65        const STRICT = 0x0800;
66        const SYNTHETIC = 0x1000;
67    }
68}
69
70/// Constant pool entry tags.
71pub mod cp_tag {
72    pub const UTF8: u8 = 1;
73    pub const INTEGER: u8 = 3;
74    pub const FLOAT: u8 = 4;
75    pub const LONG: u8 = 5;
76    pub const DOUBLE: u8 = 6;
77    pub const CLASS: u8 = 7;
78    pub const STRING: u8 = 8;
79    pub const FIELDREF: u8 = 9;
80    pub const METHODREF: u8 = 10;
81    pub const INTERFACE_METHODREF: u8 = 11;
82    pub const NAME_AND_TYPE: u8 = 12;
83    pub const METHOD_HANDLE: u8 = 15;
84    pub const METHOD_TYPE: u8 = 16;
85    pub const DYNAMIC: u8 = 17;
86    pub const INVOKE_DYNAMIC: u8 = 18;
87    pub const MODULE: u8 = 19;
88    pub const PACKAGE: u8 = 20;
89}
90
91/// Method handle reference kinds.
92pub mod ref_kind {
93    pub const GETFIELD: u8 = 1;
94    pub const GETSTATIC: u8 = 2;
95    pub const PUTFIELD: u8 = 3;
96    pub const PUTSTATIC: u8 = 4;
97    pub const INVOKEVIRTUAL: u8 = 5;
98    pub const INVOKESTATIC: u8 = 6;
99    pub const INVOKESPECIAL: u8 = 7;
100    pub const NEWINVOKESPECIAL: u8 = 8;
101    pub const INVOKEINTERFACE: u8 = 9;
102}
103
104/// A constant pool entry. Index 0 is unused; entries are 1-indexed.
105/// Long and Double entries occupy two slots.
106#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
107#[derive(Debug, Clone)]
108pub enum ConstantPoolEntry {
109    Utf8(Utf8Info),
110    Integer(IntegerInfo),
111    Float(FloatInfo),
112    Long(LongInfo),
113    Double(DoubleInfo),
114    Class(ClassInfo),
115    String(StringInfo),
116    Fieldref(FieldrefInfo),
117    Methodref(MethodrefInfo),
118    InterfaceMethodref(InterfaceMethodrefInfo),
119    NameAndType(NameAndTypeInfo),
120    MethodHandle(MethodHandleInfo),
121    MethodType(MethodTypeInfo),
122    Dynamic(DynamicInfo),
123    InvokeDynamic(InvokeDynamicInfo),
124    Module(ModuleInfo),
125    Package(PackageInfo),
126}
127
128#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
129#[derive(Debug, Clone)]
130pub struct Utf8Info {
131    pub value: String,
132}
133
134#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
135#[derive(Debug, Clone)]
136pub struct IntegerInfo {
137    pub value: i32,
138}
139
140#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141#[derive(Debug, Clone)]
142pub struct FloatInfo {
143    pub value: f32,
144}
145
146#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
147#[derive(Debug, Clone)]
148pub struct LongInfo {
149    pub value: i64,
150}
151
152#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
153#[derive(Debug, Clone)]
154pub struct DoubleInfo {
155    pub value: f64,
156}
157
158#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
159#[derive(Debug, Clone)]
160pub struct ClassInfo {
161    pub name_index: u16,
162}
163
164#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
165#[derive(Debug, Clone)]
166pub struct StringInfo {
167    pub string_index: u16,
168}
169
170#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
171#[derive(Debug, Clone)]
172pub struct FieldrefInfo {
173    pub class_index: u16,
174    pub name_and_type_index: u16,
175}
176
177#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
178#[derive(Debug, Clone)]
179pub struct MethodrefInfo {
180    pub class_index: u16,
181    pub name_and_type_index: u16,
182}
183
184#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
185#[derive(Debug, Clone)]
186pub struct InterfaceMethodrefInfo {
187    pub class_index: u16,
188    pub name_and_type_index: u16,
189}
190
191#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
192#[derive(Debug, Clone)]
193pub struct NameAndTypeInfo {
194    pub name_index: u16,
195    pub descriptor_index: u16,
196}
197
198#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
199#[derive(Debug, Clone)]
200pub struct MethodHandleInfo {
201    pub reference_kind: u8,
202    pub reference_index: u16,
203}
204
205#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
206#[derive(Debug, Clone)]
207pub struct MethodTypeInfo {
208    pub descriptor_index: u16,
209}
210
211#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
212#[derive(Debug, Clone)]
213pub struct DynamicInfo {
214    pub bootstrap_method_attr_index: u16,
215    pub name_and_type_index: u16,
216}
217
218#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
219#[derive(Debug, Clone)]
220pub struct InvokeDynamicInfo {
221    pub bootstrap_method_attr_index: u16,
222    pub name_and_type_index: u16,
223}
224
225#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
226#[derive(Debug, Clone)]
227pub struct ModuleInfo {
228    pub name_index: u16,
229}
230
231#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
232#[derive(Debug, Clone)]
233pub struct PackageInfo {
234    pub name_index: u16,
235}
236
237#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
238#[derive(Debug, Clone)]
239pub struct FieldInfo {
240    pub access_flags: FieldAccessFlags,
241    pub name_index: u16,
242    pub descriptor_index: u16,
243    pub attributes: Vec<AttributeInfo>,
244}
245
246#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
247#[derive(Debug, Clone)]
248pub struct MethodInfo {
249    pub access_flags: MethodAccessFlags,
250    pub name_index: u16,
251    pub descriptor_index: u16,
252    pub attributes: Vec<AttributeInfo>,
253}
254
255/// Generic attribute info. Specialized attributes are parsed separately.
256#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
257#[derive(Debug, Clone)]
258pub struct AttributeInfo {
259    pub attribute_name_index: u16,
260    pub info: Vec<u8>,
261}
262
263// Specialized attribute data structures
264
265#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
266#[derive(Debug, Clone)]
267pub struct CodeAttribute {
268    pub max_stack: u16,
269    pub max_locals: u16,
270    pub code: Vec<u8>,
271    pub exception_table: Vec<ExceptionTableEntry>,
272    pub attributes: Vec<AttributeInfo>,
273}
274
275#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
276#[derive(Debug, Clone)]
277pub struct ExceptionTableEntry {
278    pub start_pc: u16,
279    pub end_pc: u16,
280    pub handler_pc: u16,
281    pub catch_type: u16,
282}
283
284#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
285#[derive(Debug, Clone)]
286pub struct ConstantValueAttribute {
287    pub constantvalue_index: u16,
288}
289
290#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
291#[derive(Debug, Clone)]
292pub struct ExceptionsAttribute {
293    pub exception_index_table: Vec<u16>,
294}
295
296#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
297#[derive(Debug, Clone)]
298pub struct BootstrapMethodsAttribute {
299    pub bootstrap_methods: Vec<BootstrapMethodEntry>,
300}
301
302#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
303#[derive(Debug, Clone)]
304pub struct BootstrapMethodEntry {
305    pub bootstrap_method_ref: u16,
306    pub bootstrap_arguments: Vec<u16>,
307}
308
309#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
310#[derive(Debug, Clone)]
311pub struct StackMapTableAttribute {
312    pub entries: Vec<StackMapFrame>,
313}
314
315#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
316#[derive(Debug, Clone)]
317pub enum StackMapFrame {
318    SameFrame {
319        frame_type: u8,
320    },
321    SameLocals1StackItemFrame {
322        frame_type: u8,
323        stack: VerificationTypeInfo,
324    },
325    SameLocals1StackItemFrameExtended {
326        offset_delta: u16,
327        stack: VerificationTypeInfo,
328    },
329    ChopFrame {
330        frame_type: u8,
331        offset_delta: u16,
332    },
333    SameFrameExtended {
334        offset_delta: u16,
335    },
336    AppendFrame {
337        frame_type: u8,
338        offset_delta: u16,
339        locals: Vec<VerificationTypeInfo>,
340    },
341    FullFrame {
342        offset_delta: u16,
343        locals: Vec<VerificationTypeInfo>,
344        stack: Vec<VerificationTypeInfo>,
345    },
346}
347
348#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
349#[derive(Debug, Clone)]
350pub enum VerificationTypeInfo {
351    Top,
352    Integer,
353    Float,
354    Double,
355    Long,
356    Null,
357    UninitializedThis,
358    Object { cpool_index: u16 },
359    Uninitialized { offset: u16 },
360}
361
362#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
363#[derive(Debug, Clone)]
364pub struct InnerClass {
365    pub inner_class_info_index: u16,
366    pub outer_class_info_index: u16,
367    pub inner_name_index: u16,
368    pub inner_class_access_flags: ClassAccessFlags,
369}
370
371#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
372#[derive(Debug, Clone)]
373pub struct InnerClassesAttribute {
374    pub classes: Vec<InnerClass>,
375}
376
377#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
378#[derive(Debug, Clone)]
379pub struct SourceFileAttribute {
380    pub sourcefile_index: u16,
381}
382
383#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
384#[derive(Debug, Clone)]
385pub struct LineNumberTableAttribute {
386    pub line_number_table: Vec<LineNumberEntry>,
387}
388
389#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
390#[derive(Debug, Clone)]
391pub struct LineNumberEntry {
392    pub start_pc: u16,
393    pub line_number: u16,
394}
395
396#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
397#[derive(Debug, Clone)]
398pub struct LocalVariableTableAttribute {
399    pub local_variable_table: Vec<LocalVariableEntry>,
400}
401
402#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
403#[derive(Debug, Clone)]
404pub struct LocalVariableEntry {
405    pub start_pc: u16,
406    pub length: u16,
407    pub name_index: u16,
408    pub descriptor_index: u16,
409    pub index: u16,
410}
411
412#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
413#[derive(Debug, Clone)]
414pub struct LocalVariableTypeTableAttribute {
415    pub local_variable_type_table: Vec<LocalVariableTypeEntry>,
416}
417
418#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
419#[derive(Debug, Clone)]
420pub struct LocalVariableTypeEntry {
421    pub start_pc: u16,
422    pub length: u16,
423    pub name_index: u16,
424    pub signature_index: u16,
425    pub index: u16,
426}
427
428#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
429#[derive(Debug, Clone)]
430pub struct Annotation {
431    pub type_index: u16,
432    pub element_value_pairs: Vec<(u16, ElementValue)>,
433}
434
435#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
436#[derive(Debug, Clone)]
437pub enum ElementValue {
438    Byte {
439        const_value_index: u16,
440    },
441    Char {
442        const_value_index: u16,
443    },
444    Double {
445        const_value_index: u16,
446    },
447    Float {
448        const_value_index: u16,
449    },
450    Int {
451        const_value_index: u16,
452    },
453    Long {
454        const_value_index: u16,
455    },
456    Short {
457        const_value_index: u16,
458    },
459    Boolean {
460        const_value_index: u16,
461    },
462    String {
463        const_value_index: u16,
464    },
465    Enum {
466        type_name_index: u16,
467        const_name_index: u16,
468    },
469    Class {
470        class_info_index: u16,
471    },
472    AnnotationType {
473        annotation: Annotation,
474    },
475    Array {
476        values: Vec<ElementValue>,
477    },
478}
479
480#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
481#[derive(Debug, Clone)]
482pub struct RuntimeAnnotationsAttribute {
483    pub annotations: Vec<Annotation>,
484}
485
486#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
487#[derive(Debug, Clone)]
488pub struct ParameterAnnotation {
489    pub annotations: Vec<Annotation>,
490}
491
492#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
493#[derive(Debug, Clone)]
494pub struct RuntimeParameterAnnotationsAttribute {
495    pub parameter_annotations: Vec<ParameterAnnotation>,
496}
497
498/// Target type for a type annotation (JVMS 4.7.20).
499#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
500#[derive(Debug, Clone)]
501pub enum TypeAnnotationTarget {
502    TypeParameter {
503        type_parameter_index: u8,
504    },
505    SuperType {
506        super_type_index: u16,
507    },
508    TypeParameterBound {
509        type_parameter_index: u8,
510        bound_index: u8,
511    },
512    Empty,
513    FormalParameter {
514        formal_parameter_index: u8,
515    },
516    Throws {
517        throws_type_index: u16,
518    },
519    LocalVar {
520        table: Vec<LocalVarTargetEntry>,
521    },
522    Catch {
523        exception_table_index: u16,
524    },
525    Offset {
526        offset: u16,
527    },
528    TypeArgument {
529        offset: u16,
530        type_argument_index: u8,
531    },
532}
533
534#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
535#[derive(Debug, Clone)]
536pub struct LocalVarTargetEntry {
537    pub start_pc: u16,
538    pub length: u16,
539    pub index: u16,
540}
541
542/// A type annotation (JVMS 4.7.20).
543#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
544#[derive(Debug, Clone)]
545pub struct TypeAnnotation {
546    pub target: TypeAnnotationTarget,
547    pub target_path: Vec<TypePathEntry>,
548    pub type_index: u16,
549    pub element_value_pairs: Vec<(u16, ElementValue)>,
550}
551
552/// A step in the type_path of a type annotation.
553#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
554#[derive(Debug, Clone)]
555pub struct TypePathEntry {
556    pub type_path_kind: u8,
557    pub type_argument_index: u8,
558}
559
560#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
561#[derive(Debug, Clone)]
562pub struct RuntimeTypeAnnotationsAttribute {
563    pub annotations: Vec<TypeAnnotation>,
564}
565
566#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
567#[derive(Debug, Clone)]
568pub struct NestHostAttribute {
569    pub host_class_index: u16,
570}
571
572#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
573#[derive(Debug, Clone)]
574pub struct NestMembersAttribute {
575    pub classes: Vec<u16>,
576}
577
578#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
579#[derive(Debug, Clone)]
580pub struct RecordAttribute {
581    pub components: Vec<RecordComponentInfo>,
582}
583
584#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
585#[derive(Debug, Clone)]
586pub struct RecordComponentInfo {
587    pub name_index: u16,
588    pub descriptor_index: u16,
589    pub attributes: Vec<AttributeInfo>,
590}
591
592#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
593#[derive(Debug, Clone)]
594pub struct PermittedSubclassesAttribute {
595    pub classes: Vec<u16>,
596}
597
598/// Parsed attribute with its specialized form if recognized.
599#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
600#[derive(Debug, Clone)]
601pub enum ParsedAttribute {
602    Code(CodeAttribute),
603    ConstantValue(ConstantValueAttribute),
604    Exceptions(ExceptionsAttribute),
605    BootstrapMethods(BootstrapMethodsAttribute),
606    StackMapTable(StackMapTableAttribute),
607    InnerClasses(InnerClassesAttribute),
608    SourceFile(SourceFileAttribute),
609    LineNumberTable(LineNumberTableAttribute),
610    LocalVariableTable(LocalVariableTableAttribute),
611    LocalVariableTypeTable(LocalVariableTypeTableAttribute),
612    RuntimeVisibleAnnotations(RuntimeAnnotationsAttribute),
613    RuntimeInvisibleAnnotations(RuntimeAnnotationsAttribute),
614    RuntimeVisibleParameterAnnotations(RuntimeParameterAnnotationsAttribute),
615    RuntimeInvisibleParameterAnnotations(RuntimeParameterAnnotationsAttribute),
616    RuntimeVisibleTypeAnnotations(RuntimeTypeAnnotationsAttribute),
617    RuntimeInvisibleTypeAnnotations(RuntimeTypeAnnotationsAttribute),
618    NestHost(NestHostAttribute),
619    NestMembers(NestMembersAttribute),
620    Record(RecordAttribute),
621    PermittedSubclasses(PermittedSubclassesAttribute),
622    Deprecated,
623    Synthetic,
624    Signature { signature_index: u16 },
625    Unknown(AttributeInfo),
626}
627
628impl ConstantPoolEntry {
629    /// Returns the tag byte for this constant pool entry.
630    pub fn tag(&self) -> u8 {
631        match self {
632            ConstantPoolEntry::Utf8(_) => cp_tag::UTF8,
633            ConstantPoolEntry::Integer(_) => cp_tag::INTEGER,
634            ConstantPoolEntry::Float(_) => cp_tag::FLOAT,
635            ConstantPoolEntry::Long(_) => cp_tag::LONG,
636            ConstantPoolEntry::Double(_) => cp_tag::DOUBLE,
637            ConstantPoolEntry::Class(_) => cp_tag::CLASS,
638            ConstantPoolEntry::String(_) => cp_tag::STRING,
639            ConstantPoolEntry::Fieldref(_) => cp_tag::FIELDREF,
640            ConstantPoolEntry::Methodref(_) => cp_tag::METHODREF,
641            ConstantPoolEntry::InterfaceMethodref(_) => cp_tag::INTERFACE_METHODREF,
642            ConstantPoolEntry::NameAndType(_) => cp_tag::NAME_AND_TYPE,
643            ConstantPoolEntry::MethodHandle(_) => cp_tag::METHOD_HANDLE,
644            ConstantPoolEntry::MethodType(_) => cp_tag::METHOD_TYPE,
645            ConstantPoolEntry::Dynamic(_) => cp_tag::DYNAMIC,
646            ConstantPoolEntry::InvokeDynamic(_) => cp_tag::INVOKE_DYNAMIC,
647            ConstantPoolEntry::Module(_) => cp_tag::MODULE,
648            ConstantPoolEntry::Package(_) => cp_tag::PACKAGE,
649        }
650    }
651
652    /// Long and Double take two constant pool slots.
653    pub fn takes_two_slots(&self) -> bool {
654        matches!(
655            self,
656            ConstantPoolEntry::Long(_) | ConstantPoolEntry::Double(_)
657        )
658    }
659}
660
661impl ClassFile {
662    /// Resolve the class name from this_class index.
663    pub fn this_class_name(&self) -> Option<&str> {
664        crate::constant_pool::get_utf8(&self.constant_pool, self.this_class)
665    }
666
667    /// Resolve the super class name from super_class index.
668    pub fn super_class_name(&self) -> Option<&str> {
669        if self.super_class == 0 {
670            return None;
671        }
672        crate::constant_pool::get_utf8(&self.constant_pool, self.super_class)
673    }
674
675    /// Get the name of a method from its name_index.
676    pub fn method_name(&self, method: &MethodInfo) -> Option<&str> {
677        crate::constant_pool::get_utf8(&self.constant_pool, method.name_index)
678    }
679
680    /// Get the descriptor of a method from its descriptor_index.
681    pub fn method_descriptor(&self, method: &MethodInfo) -> Option<&str> {
682        crate::constant_pool::get_utf8(&self.constant_pool, method.descriptor_index)
683    }
684
685    /// Get the name of a field from its name_index.
686    pub fn field_name(&self, field: &FieldInfo) -> Option<&str> {
687        crate::constant_pool::get_utf8(&self.constant_pool, field.name_index)
688    }
689
690    /// Get the descriptor of a field from its descriptor_index.
691    pub fn field_descriptor(&self, field: &FieldInfo) -> Option<&str> {
692        crate::constant_pool::get_utf8(&self.constant_pool, field.descriptor_index)
693    }
694
695    /// Get the Java version as (major, minor).
696    pub fn version(&self) -> (u16, u16) {
697        (self.major_version, self.minor_version)
698    }
699}