use crate::err::AsmResult;
use crate::constants::Constants;
use crate::impls::jvms::r::ReadContext;
use crate::impls::jvms::r::transform::transform_attrs;
use crate::impls::jvms::r::util::read_utf8_from_cp;
use crate::jvms::attr::{Attribute, ExceptionTable, StackMapFrame};
use crate::jvms::element::{AttributeInfo, CPInfo};
pub(crate) fn transform_attr(attribute_info: &AttributeInfo, cp: &Vec<CPInfo>) -> AsmResult<AttributeInfo> {
let attribute_name_index = attribute_info.attribute_name_index;
let attribute_length = attribute_info.attribute_length;
let info = attribute_info.info.clone();
let Attribute::Custom(bytes) = info else { return Ok(attribute_info.clone()); };
let mut context = ReadContext::big_endian(&bytes);
let utf8 = read_utf8_from_cp(attribute_name_index as usize, cp)?;
let attr = match utf8.as_ref() {
Constants::CONSTANT_VALUE => Attribute::ConstantValue {
constantvalue_index: context.read()?,
},
Constants::CODE => {
let max_stack: u16 = context.read()?;
let max_locals: u16 = context.read()?;
let code_length: u32 = context.read()?;
let code: Vec<u8> = context.read_vec(code_length as usize)?;
let exception_table_length: u16 = context.read()?;
let exception_table: Vec<ExceptionTable> = context.read_vec(exception_table_length)?;
let attributes_count: u16 = context.read()?;
let mut attributes: Vec<AttributeInfo> = context.read_vec(attributes_count)?;
transform_attrs(&mut attributes, cp)?;
Attribute::Code {
max_stack, max_locals,
code_length, code,
exception_table_length, exception_table,
attributes_count, attributes,
}
},
Constants::STACK_MAP_TABLE => {
let number_of_entries: u16 = context.read()?;
let entries: Vec<StackMapFrame> = context.read_vec(number_of_entries)?;
Attribute::StackMapTable { number_of_entries, entries }
},
Constants::EXCEPTIONS => {
let number_of_exceptions = context.read()?;
let exception_index_table = context.read_vec(number_of_exceptions)?;
Attribute::Exceptions { number_of_exceptions, exception_index_table }
},
Constants::INNER_CLASSES => {
let number_of_classes = context.read()?;
let classes = context.read_vec(number_of_classes)?;
Attribute::InnerClasses { number_of_classes, classes, }
}
Constants::ENCLOSING_METHOD => Attribute::EnclosingMethod {
class_index: context.read()?, method_index: context.read()?,
},
Constants::SYNTHETIC => Attribute::Synthetic,
Constants::SIGNATURE => Attribute::Signature {
signature_index: context.read()?,
},
Constants::SOURCE_FILE => Attribute::SourceFile {
sourcefile_index: context.read()?,
},
Constants::SOURCE_DEBUG_EXTENSION => Attribute::SourceDebugExtension {
debug_extension: bytes,
},
Constants::LINE_NUMBER_TABLE => {
let line_number_table_length = context.read()?;
let line_number_table = context.read_vec(line_number_table_length)?;
Attribute::LineNumberTable { line_number_table_length, line_number_table }
},
Constants::LOCAL_VARIABLE_TABLE => {
let local_variable_table_length = context.read()?;
let local_variable_table = context.read_vec(local_variable_table_length)?;
Attribute::LocalVariableTable { local_variable_table_length, local_variable_table }
},
Constants::LOCAL_VARIABLE_TYPE_TABLE => {
let local_variable_type_table_length = context.read()?;
let local_variable_table = context.read_vec(local_variable_type_table_length)?;
Attribute::LocalVariableTypeTable { local_variable_type_table_length, local_variable_table }
},
Constants::DEPRECATED => Attribute::Deprecated,
Constants::RUNTIME_VISIBLE_ANNOTATIONS => {
let num_annotations = context.read()?;
let annotations = context.read_vec(num_annotations)?;
Attribute::RuntimeVisibleAnnotations { num_annotations, annotations }
},
Constants::RUNTIME_INVISIBLE_ANNOTATIONS => {
let num_annotations = context.read()?;
let annotations = context.read_vec(num_annotations)?;
Attribute::RuntimeInvisibleAnnotations { num_annotations, annotations }
},
Constants::RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS => {
let num_parameters = context.read()?;
let parameter_annotations = context.read_vec(num_parameters)?;
Attribute::RuntimeVisibleParameterAnnotations { num_parameters, parameter_annotations }
},
Constants::RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS => {
let num_parameters = context.read()?;
let parameter_annotations = context.read_vec(num_parameters)?;
Attribute::RuntimeInvisibleParameterAnnotations { num_parameters, parameter_annotations }
},
Constants::RUNTIME_VISIBLE_TYPE_ANNOTATIONS => {
let num_parameters = context.read()?;
let annotations = context.read_vec(num_parameters)?;
Attribute::RuntimeVisibleTypeAnnotations { num_parameters, annotations }
},
Constants::RUNTIME_INVISIBLE_TYPE_ANNOTATIONS => {
let num_parameters = context.read()?;
let annotations = context.read_vec(num_parameters)?;
Attribute::RuntimeVisibleTypeAnnotations { num_parameters, annotations }
},
Constants::ANNOTATION_DEFAULT => Attribute::AnnotationDefault { default_value: context.read()? },
Constants::BOOTSTRAP_METHODS => {
let num_bootstrap_methods = context.read()?;
let bootstrap_methods = context.read_vec(num_bootstrap_methods)?;
Attribute::BootstrapMethods { num_bootstrap_methods, bootstrap_methods }
},
Constants::METHOD_PARAMETERS => {
let parameters_count = context.read()?;
let parameters = context.read_vec(parameters_count)?;
Attribute::MethodParameters { parameters_count, parameters }
},
Constants::MODULE => {
let module_name_index: u16 = context.read()?;
let module_flags: u16 = context.read()?;
let module_version_index: u16 = context.read()?;
let requires_count: u16 = context.read()?;
let requires = context.read_vec(requires_count)?;
let exports_count: u16 = context.read()?;
let exports = context.read_vec(exports_count)?;
let opens_count: u16 = context.read()?;
let opens = context.read_vec(opens_count)?;
let uses_count: u16 = context.read()?;
let uses_index: Vec<u16> = context.read_vec(uses_count)?;
let provides_count: u16 = context.read()?;
let provides = context.read_vec(provides_count)?;
Attribute::Module {
module_name_index, module_flags, module_version_index,
requires_count, requires, exports_count, exports,
opens_count, opens, uses_count, uses_index, provides_count, provides,
}
},
Constants::MODULE_PACKAGES => {
let package_count = context.read()?;
let package_index = context.read_vec(package_count)?;
Attribute::ModulePackages { package_count, package_index }
},
Constants::MODULE_MAIN_CLASS => Attribute::ModuleMainClass { main_class_index: context.read()? },
Constants::NEST_HOST => Attribute::NestHost { host_class_index: context.read()? },
Constants::NEST_MEMBERS => {
let number_of_classes = context.read()?;
let classes = context.read_vec(number_of_classes)?;
Attribute::NestMembers { number_of_classes, classes }
},
Constants::RECORD => {
let components_count = context.read()?;
let components = context.read_vec(components_count)?;
Attribute::Record { components_count, components }
},
Constants::PERMITTED_SUBCLASSES => {
let number_of_classes = context.read()?;
let classes = context.read_vec(number_of_classes)?;
Attribute::PermittedSubclasses { number_of_classes, classes }
},
_ => Attribute::Custom(bytes),
};
let attribute_info = AttributeInfo {
attribute_name_index,
attribute_length,
info: attr,
};
Ok(attribute_info)
}