From a7fa802007a1481d5fb1b6c435ac197031bb6cb4 Mon Sep 17 00:00:00 2001 From: brianheineman Date: Fri, 24 Jan 2025 14:51:01 -0700 Subject: [PATCH] docs: add enum documentation --- .../src/attributes/attribute.rs | 44 ++- .../src/attributes/exception_table_entry.rs | 3 + .../src/attributes/instruction.rs | 286 +++++++++++++++++- ristretto_classfile/src/constant.rs | 21 +- ristretto_classfile/src/constant_pool.rs | 11 +- 5 files changed, 344 insertions(+), 21 deletions(-) diff --git a/ristretto_classfile/src/attributes/attribute.rs b/ristretto_classfile/src/attributes/attribute.rs index 38c9e6ff..f5c9f1f7 100644 --- a/ristretto_classfile/src/attributes/attribute.rs +++ b/ristretto_classfile/src/attributes/attribute.rs @@ -37,10 +37,12 @@ const VERSION_61_0: Version = Version::Java17 { minor: 0 }; /// See: #[derive(Clone, Debug, PartialEq)] pub enum Attribute { + /// See: ConstantValue { name_index: u16, constant_value_index: u16, }, + /// See: Code { name_index: u16, max_stack: u16, @@ -49,89 +51,107 @@ pub enum Attribute { exception_table: Vec, attributes: Vec, }, + /// See: StackMapTable { name_index: u16, frames: Vec, }, + /// See: Exceptions { name_index: u16, exception_indexes: Vec, }, + /// See: InnerClasses { name_index: u16, classes: Vec, }, + /// See: EnclosingMethod { name_index: u16, class_index: u16, method_index: u16, }, - Synthetic { - name_index: u16, - }, + /// See: + Synthetic { name_index: u16 }, + /// See: Signature { name_index: u16, signature_index: u16, }, + /// See: SourceFile { name_index: u16, source_file_index: u16, }, + /// See: SourceDebugExtension { name_index: u16, debug_extension: String, }, + /// See: LineNumberTable { name_index: u16, line_numbers: Vec, }, + /// See: LocalVariableTable { name_index: u16, variables: Vec, }, + /// See: LocalVariableTypeTable { name_index: u16, variable_types: Vec, }, - Deprecated { - name_index: u16, - }, + /// See: + Deprecated { name_index: u16 }, + /// See: RuntimeVisibleAnnotations { name_index: u16, annotations: Vec, }, + /// See: RuntimeInvisibleAnnotations { name_index: u16, annotations: Vec, }, + /// See: RuntimeVisibleParameterAnnotations { name_index: u16, parameter_annotations: Vec, }, + /// See: RuntimeInvisibleParameterAnnotations { name_index: u16, parameter_annotations: Vec, }, + /// See: RuntimeVisibleTypeAnnotations { name_index: u16, type_annotations: Vec, }, + /// See: RuntimeInvisibleTypeAnnotations { name_index: u16, type_annotations: Vec, }, + /// See: AnnotationDefault { name_index: u16, element: AnnotationElement, }, + /// See: BootstrapMethods { name_index: u16, methods: Vec, }, + /// See: MethodParameters { name_index: u16, parameters: Vec, }, + /// See: Module { name_index: u16, module_name_index: u16, @@ -143,34 +163,38 @@ pub enum Attribute { uses: Vec, provides: Vec, }, + /// See: ModulePackages { name_index: u16, package_indexes: Vec, }, + /// See: ModuleMainClass { name_index: u16, main_class_index: u16, }, + /// See: NestHost { name_index: u16, host_class_index: u16, }, + /// See: NestMembers { name_index: u16, class_indexes: Vec, }, + /// See: Record { name_index: u16, records: Vec, }, + /// See: PermittedSubclasses { name_index: u16, class_indexes: Vec, }, - Unknown { - name_index: u16, - info: Vec, - }, + /// Used to support reading future classes where the structure is not known beforehand. + Unknown { name_index: u16, info: Vec }, } impl Attribute { diff --git a/ristretto_classfile/src/attributes/exception_table_entry.rs b/ristretto_classfile/src/attributes/exception_table_entry.rs index b6ce0fa7..e67a8158 100644 --- a/ristretto_classfile/src/attributes/exception_table_entry.rs +++ b/ristretto_classfile/src/attributes/exception_table_entry.rs @@ -6,6 +6,9 @@ use std::ops::Range; /// Implementation of an `ExceptionTable` entry. /// +/// This implementation differs from the specification. The program counter offsets represent +/// an index into the logical code instructions instead of the physical byte offsets. +/// /// See: #[derive(Clone, Debug, PartialEq)] pub struct ExceptionTableEntry { diff --git a/ristretto_classfile/src/attributes/instruction.rs b/ristretto_classfile/src/attributes/instruction.rs index 7658396a..789e5182 100644 --- a/ristretto_classfile/src/attributes/instruction.rs +++ b/ristretto_classfile/src/attributes/instruction.rs @@ -14,236 +14,510 @@ use std::io::Cursor; #[expect(non_camel_case_types)] #[derive(Clone, Debug, PartialEq)] pub enum Instruction { + /// See: Nop, + /// See: Aconst_null, + /// See: Iconst_m1, + /// See: Iconst_0, + /// See: Iconst_1, + /// See: Iconst_2, + /// See: Iconst_3, + /// See: Iconst_4, + /// See: Iconst_5, + /// See: Lconst_0, + /// See: Lconst_1, + /// See: Fconst_0, + /// See: Fconst_1, + /// See: Fconst_2, + /// See: Dconst_0, + /// See: Dconst_1, + /// See: Bipush(i8), + /// See: Sipush(i16), + /// See: Ldc(u8), + /// See: Ldc_w(u16), + /// See: Ldc2_w(u16), + /// See: Iload(u8), + /// See: Lload(u8), + /// See: Fload(u8), + /// See: Dload(u8), + /// See: Aload(u8), + /// See: Iload_0, + /// See: Iload_1, + /// See: Iload_2, + /// See: Iload_3, + /// See: Lload_0, + /// See: Lload_1, + /// See: Lload_2, + /// See: Lload_3, + /// See: Fload_0, + /// See: Fload_1, + /// See: Fload_2, + /// See: Fload_3, + /// See: Dload_0, + /// See: Dload_1, + /// See: Dload_2, + /// See: Dload_3, + /// See: Aload_0, + /// See: Aload_1, + /// See: Aload_2, + /// See: Aload_3, + /// See: Iaload, + /// See: Laload, + /// See: Faload, + /// See: Daload, + /// See: Aaload, + /// See: Baload, + /// See: Caload, + /// See: Saload, + /// See: Istore(u8), + /// See: Lstore(u8), + /// See: Fstore(u8), + /// See: Dstore(u8), + /// See: Astore(u8), + /// See: Istore_0, + /// See: Istore_1, + /// See: Istore_2, + /// See: Istore_3, + /// See: Lstore_0, + /// See: Lstore_1, + /// See: Lstore_2, + /// See: Lstore_3, + /// See: Fstore_0, + /// See: Fstore_1, + /// See: Fstore_2, + /// See: Fstore_3, + /// See: Dstore_0, + /// See: Dstore_1, + /// See: Dstore_2, + /// See: Dstore_3, + /// See: Astore_0, + /// See: Astore_1, + /// See: Astore_2, + /// See: Astore_3, + /// See: Iastore, + /// See: Lastore, + /// See: Fastore, + /// See: Dastore, + /// See: Aastore, + /// See: Bastore, + /// See: Castore, + /// See: Sastore, + /// See: Pop, + /// See: Pop2, + /// See: Dup, + /// See: Dup_x1, + /// See: Dup_x2, + /// See: Dup2, + /// See: Dup2_x1, + /// See: Dup2_x2, + /// See: Swap, + /// See: Iadd, + /// See: Ladd, + /// See: Fadd, + /// See: Dadd, + /// See: Isub, + /// See: Lsub, + /// See: Fsub, + /// See: Dsub, + /// See: Imul, + /// See: Lmul, + /// See: Fmul, + /// See: Dmul, + /// See: Idiv, + /// See: Ldiv, + /// See: Fdiv, + /// See: Ddiv, + /// See: Irem, + /// See: Lrem, + /// See: Frem, + /// See: Drem, + /// See: Ineg, + /// See: Lneg, + /// See: Fneg, + /// See: Dneg, + /// See: Ishl, + /// See: Lshl, + /// See: Ishr, + /// See: Lshr, + /// See: Iushr, + /// See: Lushr, + /// See: Iand, + /// See: Land, + /// See: Ior, + /// See: Lor, + /// See: Ixor, + /// See: Lxor, + /// See: Iinc(u8, i8), + /// See: I2l, + /// See: I2f, + /// See: I2d, + /// See: L2i, + /// See: L2f, + /// See: L2d, + /// See: F2i, + /// See: F2l, + /// See: F2d, + /// See: D2i, + /// See: D2l, + /// See: D2f, + /// See: I2b, + /// See: I2c, + /// See: I2s, + /// See: Lcmp, + /// See: Fcmpl, + /// See: Fcmpg, + /// See: Dcmpl, + /// See: Dcmpg, + /// See: Ifeq(u16), + /// See: Ifne(u16), + /// See: Iflt(u16), + /// See: Ifge(u16), + /// See: Ifgt(u16), + /// See: Ifle(u16), + /// See: If_icmpeq(u16), + /// See: If_icmpne(u16), + /// See: If_icmplt(u16), + /// See: If_icmpge(u16), + /// See: If_icmpgt(u16), + /// See: If_icmple(u16), + /// See: If_acmpeq(u16), + /// See: If_acmpne(u16), + /// See: Goto(u16), + /// See: Jsr(u16), + /// See: Ret(u8), + /// See: Tableswitch { default: i32, low: i32, high: i32, offsets: Vec, }, + /// See: Lookupswitch { default: i32, pairs: IndexMap, }, + /// See: Ireturn, + /// See: Lreturn, + /// See: Freturn, + /// See: Dreturn, + /// See: Areturn, + /// See: Return, + /// See: Getstatic(u16), + /// See: Putstatic(u16), + /// See: Getfield(u16), + /// See: Putfield(u16), + /// See: Invokevirtual(u16), + /// See: Invokespecial(u16), + /// See: Invokestatic(u16), + /// See: Invokeinterface(u16, u8), + /// Not implemented. Usage results in a panic. + /// + /// See: Invokedynamic(u16), + /// See: New(u16), + /// See: Newarray(ArrayType), + /// See: Anewarray(u16), + /// See: Arraylength, + /// See: Athrow, + /// See: Checkcast(u16), + /// See: Instanceof(u16), + /// Not implemented. No-op. + /// + /// See: Monitorenter, + /// Not implemented. No-op. + /// + /// See: Monitorexit, + /// See: Wide, + /// See: Multianewarray(u16, u8), + /// See: Ifnull(u16), + /// See: Ifnonnull(u16), + /// See: Goto_w(i32), + /// See: Jsr_w(i32), - // Breakpoint, Impdep1 and Impdep2 instructions are reserved for debugging and implementation - // dependent operations. - // See: https://docs.oracle.com/javase/specs/jvms/se23/html/jvms-6.html#jvms-6.2 + /// Breakpoint is reserved for debugging and implementation dependent operations. + /// Not implemented. No-op. + /// + /// See: Breakpoint, + /// Impdep1 is reserved for debugging and implementation dependent operations. + /// Not implemented. No-op. + /// + /// See: Impdep1, + /// Impdep2 is reserved for debugging and implementation dependent operations. + /// Not implemented. No-op. + /// + /// See: Impdep2, - // Wide instructions - // These are virtual instructions that are not part of the JVM spec but are used internally to - // represent wide instructions. + /// Virtual instruction that represents wide version of `iload`. This instruction is not part of + /// the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Iload_w(u16), + /// Virtual instruction that represents wide version of `lload`. This instruction is not part of + /// the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Lload_w(u16), + /// Virtual instruction that represents wide version of `fload`. This instruction is not part of + /// the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Fload_w(u16), + /// Virtual instruction that represents wide version of `dload`. This instruction is not part of + /// the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Dload_w(u16), + /// Virtual instruction that represents wide version of `aload`. This instruction is not part of + /// the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Aload_w(u16), + /// Virtual instruction that represents wide version of `istore`. This instruction is not part + /// of the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Istore_w(u16), + /// Virtual instruction that represents wide version of `lstore`. This instruction is not part + /// of the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Lstore_w(u16), + /// Virtual instruction that represents wide version of `fstore`. This instruction is not part + /// of the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Fstore_w(u16), + /// Virtual instruction that represents wide version of `dstore`. This instruction is not part + /// of the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Dstore_w(u16), + /// Virtual instruction that represents wide version of `astore`. This instruction is not part + /// of the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Astore_w(u16), + /// Virtual instruction that represents wide version of `iinc`. This instruction is not part + /// of the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Iinc_w(u16, i16), + /// Virtual instruction that represents wide version of `ret`. This instruction is not part of + /// the JVM specification is internally to efficiently represent wide instructions. + /// + /// See: + /// See: Ret_w(u16), } diff --git a/ristretto_classfile/src/constant.rs b/ristretto_classfile/src/constant.rs index d5e8a13e..d460e2e5 100644 --- a/ristretto_classfile/src/constant.rs +++ b/ristretto_classfile/src/constant.rs @@ -18,43 +18,60 @@ const VERSION_55_0: Version = Version::Java11 { minor: 0 }; /// See: #[derive(Clone, Debug, PartialEq)] pub enum Constant { + /// See: Utf8(String), + /// See: Integer(i32), + /// See: Float(f32), + /// See: Long(i64), + /// See: Double(f64), - Class(u16), // Name index (Utf8) + /// See: + Class(u16), // Name index (Utf8) + /// See: String(u16), // String index (Utf8) + /// See: FieldRef { class_index: u16, name_and_type_index: u16, }, + /// See: MethodRef { class_index: u16, name_and_type_index: u16, }, + /// See: InterfaceMethodRef { class_index: u16, name_and_type_index: u16, }, + /// See: NameAndType { name_index: u16, descriptor_index: u16, }, + /// See: MethodHandle { reference_kind: ReferenceKind, reference_index: u16, }, + /// See: MethodType(u16), // Descriptor index (NameAndType) + /// See: Dynamic { bootstrap_method_attr_index: u16, name_and_type_index: u16, }, + /// See: InvokeDynamic { bootstrap_method_attr_index: u16, name_and_type_index: u16, }, - Module(u16), // Name index (Utf8) + /// See: + Module(u16), // Name index (Utf8) + /// See: Package(u16), // Name index (Utf8) } diff --git a/ristretto_classfile/src/constant_pool.rs b/ristretto_classfile/src/constant_pool.rs index 08c37714..8d82072f 100644 --- a/ristretto_classfile/src/constant_pool.rs +++ b/ristretto_classfile/src/constant_pool.rs @@ -38,8 +38,8 @@ impl ConstantPool { /// # Errors /// If there are more than 65,534 constants in the pool. pub fn add(&mut self, constant: Constant) -> Result { - // Logically the index is self.len() + 1. However, since the constant pool is one based and - // a placeholder is added as the first entry, we can just use the length of the constants + // Logically the index is self.len() + 1. However, since the constant pool is one based a + // placeholder is added as the first entry, we can just use the length of the constants // vector to obtain the new index value. let index = u16::try_from(self.constants.len())?; self.push(constant); @@ -676,12 +676,17 @@ impl Default for ConstantPool { } } -/// All 8 byte constants (long and double) take up two entries in the constant pool; a placeholder +/// All 8 byte constants (double and long) take up two entries in the constant pool; a placeholder /// is used to facilitate efficient indexed access of constants in the pool. See the JVM spec for: /// #[derive(Clone, Debug, PartialEq)] enum ConstantEntry { Constant(Constant), + /// The constant pool is one based; a placeholder is added at position 0 to facilitate one based + /// indexing without needing to calculate an offset. The JVM specification also expects 8 byte + /// constants (e.g double and long) to take two places in the constant pool. This implementation + /// only uses one position for 8 byte constants and uses the placeholder as a way to correctly + /// offset the constant pool index. Placeholder, }