//! The "program" structure - the unit of work for the pipeline. pub mod annotations; pub mod builder; pub mod version; pub use annotations::{Annotation, AnnotationValue, TypeAnnotation}; pub use version::Version; use crate::format::StackMapFrame; use crate::insn::{Const, Insn, Label}; /// Unknown/specific attributes are stored as bytes - lossless round-trip. #[derive(Debug, Clone, PartialEq)] pub enum Attribute { SourceFile(String), LineNumberTable(Vec), LocalVariableTable(Vec), Signature(String), Exceptions(Vec), Deprecated, Synthetic, InnerClasses(Vec), /// `NestHost`: the class acting as nest host (JVMS §4.7.28). NestHost(String), /// `NestMembers`: the member classes of this nest host (JVMS §4.7.29). NestMembers(Vec), /// `PermittedSubclasses`: who may extend a sealed class (JVMS §4.7.31). /// Stored as names: pool indices go stale when the pool is rebuilt. PermittedSubclasses(Vec), /// A field's `ConstantValue` (`static final`): a value from the pool. ConstantValue(Const), /// `BootstrapMethods` for `invokedynamic` (lambdas): method + arguments. BootstrapMethods(Vec), /// `EnclosingMethod`: the class and optional method enclosing a local class. EnclosingMethod { class: String, method: Option<(String, String)>, }, /// `MethodParameters`: formal parameter names (`None` - unnamed). MethodParameters(Vec), /// `Record`: the record class's components. Record(Vec), /// `LocalVariableTypeTable`: generic local signatures (like LVT). LocalVariableTypeTable(Vec), /// `RuntimeVisibleAnnotations` (JVMS §4.7.16): parsed, not raw bytes - /// reflection reads them at runtime and raw indices go stale on write. RuntimeVisibleAnnotations(Vec), /// `RuntimeInvisibleAnnotations` (JVMS §4.7.17): CLASS-retention ones. RuntimeInvisibleAnnotations(Vec), /// `RuntimeVisibleParameterAnnotations` (JVMS §4.7.18): per-parameter /// annotations. Parsed like the class-level ones - raw pool indices go /// stale when the pool is rebuilt. RuntimeVisibleParameterAnnotations(Vec>), /// `RuntimeInvisibleParameterAnnotations` (JVMS §4.7.19). RuntimeInvisibleParameterAnnotations(Vec>), /// `RuntimeVisibleTypeAnnotations` (JVMS §4.7.20): type-use /// annotations. Parsed - raw pool indices go stale on write and ASM /// dies with `ArrayIndexOutOfBoundsException` reading them back. RuntimeVisibleTypeAnnotations(Vec), /// `RuntimeInvisibleTypeAnnotations` (JVMS §4.7.21). RuntimeInvisibleTypeAnnotations(Vec), /// `AnnotationDefault` (JVMS §4.7.22): the default value of one /// annotation member - a single `element_value` with pool references. AnnotationDefault(AnnotationValue), /// Everything else: name + raw `info` bytes (careful with pool indices). Raw { name: String, data: Vec, }, } #[derive(Debug, Clone, Copy, PartialEq)] pub struct LineNumber { /// Start label (the writer computes bytes - survives pass insertions). pub start: Label, pub line: u16, } #[derive(Debug, Clone, PartialEq)] pub struct LocalVariable { /// Visibility-range labels (the writer recomputes them into bytes). pub start: Label, pub end: Label, pub name: String, pub descriptor: String, pub index: u16, } #[derive(Debug, Clone, PartialEq)] pub struct InnerClass { pub inner: String, pub outer: Option, pub inner_name: Option, pub access_flags: u16, } /// One `bootstrap` method: a `MethodHandle`-style reference + const arguments. #[derive(Debug, Clone, PartialEq)] pub struct BootstrapMethod { /// The `reference_kind` number (JVMS §5.4.3.5). pub kind: u8, pub owner: String, pub name: String, pub descriptor: String, pub itf: bool, pub args: Vec, } /// A method's formal parameter (`MethodParameters`). #[derive(Debug, Clone, PartialEq)] pub struct MethodParameter { pub name: Option, pub access_flags: u16, } /// A `Record` component: a record class field with attributes. #[derive(Debug, Clone, PartialEq)] pub struct RecordComponent { pub name: String, pub descriptor: String, pub attributes: Vec, } /// A `LocalVariableTypeTable` entry (like `LocalVariable`, but with a signature). #[derive(Debug, Clone, PartialEq)] pub struct LocalVariableType { /// Visibility-range labels (the writer recomputes them into bytes). pub start: Label, pub end: Label, pub name: String, pub signature: String, pub index: u16, } #[derive(Debug, Clone, PartialEq)] pub struct Field { pub access_flags: u16, pub name: String, pub descriptor: String, pub attributes: Vec, } #[derive(Debug, Clone, PartialEq)] pub struct Method { pub access_flags: u16, pub name: String, pub descriptor: String, pub code: Option, pub attributes: Vec, } impl Method { /// `native`/`abstract` methods have no body. pub fn has_code(&self) -> bool { self.code.is_some() } } /// A method body. #[derive(Debug, Clone, PartialEq)] pub struct Code { pub max_stack: u16, pub max_locals: u16, /// Label markers + instructions; branches point at a [`Label`]. pub insns: Vec, pub exception_table: Vec, pub frames: Vec, pub attributes: Vec, } impl Code { /// All labels declared in the method body. pub fn labels(&self) -> Vec