mirror of
https://github.com/Noratrieb/coldsquare.git
synced 2026-01-14 16:35:10 +01:00
Refactored Attributes to be a struct
because why not
This commit is contained in:
parent
5dcee9db57
commit
3546a5b268
2 changed files with 178 additions and 170 deletions
285
src/parse/mod.rs
285
src/parse/mod.rs
|
|
@ -245,10 +245,12 @@ impl Parse for MethodInfo {
|
|||
|
||||
impl Parse for AttributeInfo {
|
||||
fn parse(data: &mut Data) -> Result<Self> {
|
||||
Ok(Self::Unknown {
|
||||
Ok(Self {
|
||||
attribute_name_index: data.u2()?,
|
||||
attribute_length: data.u4()?,
|
||||
attribute_content: parse_vec(data, data.last_u4()? as usize)?,
|
||||
inner: AttributeInfoInner::Unknown {
|
||||
attribute_content: parse_vec(data, data.last_u4()? as usize)?,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -456,13 +458,20 @@ fn resolve_attributes(class: &mut ClassFile) -> Result<()> {
|
|||
impl AttributeInfo {
|
||||
fn resolve_attribute(&mut self, pool: &[CpInfo]) -> Result<()> {
|
||||
// this is a borrow checker hack, but it works :(
|
||||
let attr = std::mem::replace(self, AttributeInfo::__Empty);
|
||||
let attr = std::mem::replace(
|
||||
self,
|
||||
AttributeInfo {
|
||||
attribute_name_index: 0,
|
||||
attribute_length: 0,
|
||||
inner: AttributeInfoInner::__Empty,
|
||||
},
|
||||
);
|
||||
|
||||
let (&index, &len, content) = match &attr {
|
||||
AttributeInfo::Unknown {
|
||||
AttributeInfo {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
attribute_content,
|
||||
inner: AttributeInfoInner::Unknown { attribute_content },
|
||||
} => (attribute_name_index, attribute_length, attribute_content),
|
||||
_ => unreachable!("Attribute already resolved"),
|
||||
};
|
||||
|
|
@ -486,127 +495,163 @@ impl AttributeInfo {
|
|||
let _ = std::mem::replace(
|
||||
self,
|
||||
match name {
|
||||
"ConstantValue" => Self::ConstantValue {
|
||||
"ConstantValue" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
constantvalue_index: data.u2()?,
|
||||
},
|
||||
"Code" => Self::Code {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
max_stack: data.u2()?,
|
||||
max_locals: data.u2()?,
|
||||
code_length: data.u4()?,
|
||||
code: parse_vec(data, data.last_u4()? as usize)?,
|
||||
exception_table_length: data.u2()?,
|
||||
exception_table: parse_vec(data, data.last_u2()?)?,
|
||||
attributes_count: data.u2()?,
|
||||
attributes: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"StackMapTable" => Self::StackMapTable {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
number_of_entries: data.u2()?,
|
||||
entries: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"Exceptions" => Self::Exceptions {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
number_of_exceptions: data.u2()?,
|
||||
exception_index_table: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"InnerClasses" => Self::InnerClasses {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
number_of_classes: data.u2()?,
|
||||
classes: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"EnclosingMethod" => Self::EnclosingMethod {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
class_index: data.u2()?,
|
||||
method_index: data.u2()?,
|
||||
},
|
||||
"Synthetic" => Self::Synthetic {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
},
|
||||
"Signature" => Self::Signature {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
signature_index: data.u2()?,
|
||||
},
|
||||
"SourceFile" => Self::SourceFile {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
sourcefile_index: data.u2()?,
|
||||
},
|
||||
"SourceDebugExtension" => Self::SourceDebugExtension {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
debug_extension: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"LineNumberTable" => Self::LineNumberTable {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
line_number_table_length: data.u2()?,
|
||||
line_number_table: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"LocalVariableTable" => Self::LocalVariableTable {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
local_variable_table_length: data.u2()?,
|
||||
local_variable_table: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"LocalVariableTypeTable" => Self::LocalVariableTypeTable {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
local_variable_table_length: data.u2()?,
|
||||
local_variable_table: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"Deprecated" => Self::Deprecated {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
},
|
||||
"RuntimeVisibleAnnotations" => Self::RuntimeVisibleAnnotations {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
num_annotations: data.u2()?,
|
||||
annotations: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"RuntimeInvisibleAnnotations" => Self::RuntimeInvisibleAnnotations {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
num_annotations: data.u2()?,
|
||||
annotations: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
"RuntimeVisibleParameterAnnotations" => Self::RuntimeVisibleParameterAnnotations {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
num_parameters: data.u1()?,
|
||||
parameter_annotations: parse_vec(data, data.last_u1()?)?,
|
||||
},
|
||||
"RuntimeInvisibleParameterAnnotations" => {
|
||||
Self::RuntimeInvisibleParameterAnnotations {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
num_parameters: data.u1()?,
|
||||
parameter_annotations: parse_vec(data, data.last_u1()?)?,
|
||||
}
|
||||
}
|
||||
"AnnotationDefault" => Self::AnnotationDefault {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
default_value: AnnotationElementValue {
|
||||
tag: data.u1()?,
|
||||
value: AnnotationElementValueValue::parse(data)?,
|
||||
inner: AttributeInfoInner::ConstantValue {
|
||||
constantvalue_index: data.u2()?,
|
||||
},
|
||||
},
|
||||
"BootstrapMethods" => Self::BootstrapMethods {
|
||||
"Code" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
num_bootstrap_methods: data.u2()?,
|
||||
bootstrap_methods: parse_vec(data, data.last_u2()?)?,
|
||||
inner: AttributeInfoInner::Code {
|
||||
max_stack: data.u2()?,
|
||||
max_locals: data.u2()?,
|
||||
code_length: data.u4()?,
|
||||
code: parse_vec(data, data.last_u4()? as usize)?,
|
||||
exception_table_length: data.u2()?,
|
||||
exception_table: parse_vec(data, data.last_u2()?)?,
|
||||
attributes_count: data.u2()?,
|
||||
attributes: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"StackMapTable" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::StackMapTable {
|
||||
number_of_entries: data.u2()?,
|
||||
entries: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"Exceptions" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::Exceptions {
|
||||
number_of_exceptions: data.u2()?,
|
||||
exception_index_table: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"InnerClasses" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::InnerClasses {
|
||||
number_of_classes: data.u2()?,
|
||||
classes: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"EnclosingMethod" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::EnclosingMethod {
|
||||
class_index: data.u2()?,
|
||||
method_index: data.u2()?,
|
||||
},
|
||||
},
|
||||
"Synthetic" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::Synthetic,
|
||||
},
|
||||
"Signature" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::Signature {
|
||||
signature_index: data.u2()?,
|
||||
},
|
||||
},
|
||||
"SourceFile" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::SourceFile {
|
||||
sourcefile_index: data.u2()?,
|
||||
},
|
||||
},
|
||||
"SourceDebugExtension" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::SourceDebugExtension {
|
||||
debug_extension: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"LineNumberTable" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::LineNumberTable {
|
||||
line_number_table_length: data.u2()?,
|
||||
line_number_table: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"LocalVariableTable" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::LocalVariableTable {
|
||||
local_variable_table_length: data.u2()?,
|
||||
local_variable_table: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"LocalVariableTypeTable" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::LocalVariableTypeTable {
|
||||
local_variable_table_length: data.u2()?,
|
||||
local_variable_table: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"Deprecated" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::Deprecated,
|
||||
},
|
||||
"RuntimeVisibleAnnotations" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::RuntimeVisibleAnnotations {
|
||||
num_annotations: data.u2()?,
|
||||
annotations: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"RuntimeInvisibleAnnotations" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::RuntimeInvisibleAnnotations {
|
||||
num_annotations: data.u2()?,
|
||||
annotations: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
"RuntimeVisibleParameterAnnotations" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::RuntimeVisibleParameterAnnotations {
|
||||
num_parameters: data.u1()?,
|
||||
parameter_annotations: parse_vec(data, data.last_u1()?)?,
|
||||
},
|
||||
},
|
||||
"RuntimeInvisibleParameterAnnotations" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::RuntimeInvisibleParameterAnnotations {
|
||||
num_parameters: data.u1()?,
|
||||
parameter_annotations: parse_vec(data, data.last_u1()?)?,
|
||||
},
|
||||
},
|
||||
"AnnotationDefault" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::AnnotationDefault {
|
||||
default_value: AnnotationElementValue {
|
||||
tag: data.u1()?,
|
||||
value: AnnotationElementValueValue::parse(data)?,
|
||||
},
|
||||
},
|
||||
},
|
||||
"BootstrapMethods" => Self {
|
||||
attribute_name_index,
|
||||
attribute_length,
|
||||
inner: AttributeInfoInner::BootstrapMethods {
|
||||
num_bootstrap_methods: data.u2()?,
|
||||
bootstrap_methods: parse_vec(data, data.last_u2()?)?,
|
||||
},
|
||||
},
|
||||
name => return Err(ParseErr(format!("Invalid Attribute name: {}", name))),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -182,26 +182,28 @@ pub struct MethodInfo {
|
|||
///
|
||||
/// _index: Index to the `constant_pool` table of any type
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
// todo refactor this into a struct + enum
|
||||
pub enum AttributeInfo {
|
||||
pub struct AttributeInfo {
|
||||
pub attribute_name_index: u2,
|
||||
pub attribute_length: u4,
|
||||
/// The attribute value
|
||||
pub inner: AttributeInfoInner,
|
||||
}
|
||||
|
||||
/// The Attributes, without the two common fields
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum AttributeInfoInner {
|
||||
__Empty,
|
||||
/// The exact kind of attribute is not known yet and will be resolved later in the process
|
||||
Unknown {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
attribute_content: Vec<u1>,
|
||||
},
|
||||
/// Only on fields, the constant value of that field
|
||||
ConstantValue {
|
||||
attribute_name_index: u2, // "ConstantValue"
|
||||
attribute_length: u4,
|
||||
/// Must be of type `Long`/`Float`/`Double`/`Integer`/`String`
|
||||
constantvalue_index: u2,
|
||||
},
|
||||
/// Only on methods, contains JVM instructions and auxiliary information for a single method
|
||||
Code {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
/// The maximum depth of the operand stack for this method
|
||||
max_stack: u2,
|
||||
/// The number of the local variables array, including the parameters
|
||||
|
|
@ -221,31 +223,22 @@ pub enum AttributeInfo {
|
|||
/// Only on the `Code` attribute, used for verification
|
||||
/// May be implicit on version >= 50.0, with no entries
|
||||
StackMapTable {
|
||||
/// Must be `Utf8`
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
number_of_entries: u2,
|
||||
entries: Vec<StackMapFrame>,
|
||||
},
|
||||
/// Only on `MethodInfo`, indicates which checked exceptions might be thrown
|
||||
Exceptions {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
number_of_exceptions: u2,
|
||||
/// Must be a `Class` constant
|
||||
exception_index_table: Vec<u2>,
|
||||
},
|
||||
/// Only on a `ClassFile`. Specifies the inner classes of a class
|
||||
InnerClasses {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
number_of_classes: u2,
|
||||
classes: Vec<AttributeInnerClass>,
|
||||
},
|
||||
/// Only on a `ClassFile`, required if it is local or anonymous
|
||||
EnclosingMethod {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4, // 4
|
||||
/// Must be a `Class` constant, the innermost enclosing class
|
||||
class_index: u2,
|
||||
/// Must be zero or `NameAndType`
|
||||
|
|
@ -253,97 +246,67 @@ pub enum AttributeInfo {
|
|||
},
|
||||
/// Can be on `ClassFile`, `FieldInfo`,or `MethodInfo`.
|
||||
/// Every generated class has to have this attribute or the `Synthetic` Accessor modifier
|
||||
Synthetic {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4, // 0
|
||||
},
|
||||
Synthetic,
|
||||
/// Can be on `ClassFile`, `FieldInfo`,or `MethodInfo`. Records generic signature information
|
||||
Signature {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4, // 2
|
||||
/// Must be `Utf8`, and a Class/Method/Field signature
|
||||
signature_index: u2,
|
||||
},
|
||||
/// Only on a `ClassFile`
|
||||
SourceFile {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4, // 2
|
||||
/// Must be `Utf8`, the name of the source filed
|
||||
sourcefile_index: u2,
|
||||
},
|
||||
/// Only on a `ClassFile`
|
||||
SourceDebugExtension {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4, // number of items in `debug_extension`
|
||||
/// A modified UTF-8 of additional debugging information
|
||||
/// A modified UTF-8 of additional debugging information, `attribute_length`: number of items in `debug_extension`
|
||||
debug_extension: Vec<u1>,
|
||||
},
|
||||
/// Only on the `Code` attribute. It includes line number information used by debuggers
|
||||
LineNumberTable {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
line_number_table_length: u2,
|
||||
line_number_table: Vec<AttributeLineNumber>,
|
||||
},
|
||||
/// Only on the `Code` attribute. It may be used to determine the value of local variables by debuggers
|
||||
LocalVariableTable {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
local_variable_table_length: u2,
|
||||
/// Note: the 3rd field is called `descriptor_index` and represents an field descriptor
|
||||
local_variable_table: Vec<AttributeLocalVariableTable>,
|
||||
},
|
||||
/// Only on the `Code` attribute. It provides signature information instead of descriptor information
|
||||
LocalVariableTypeTable {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
local_variable_table_length: u2,
|
||||
/// Note: the 3rd field is called `signature_index` and represents a field type signature
|
||||
local_variable_table: Vec<AttributeLocalVariableTable>,
|
||||
},
|
||||
/// Can be on `ClassFile`, `FieldInfo`,or `MethodInfo`. Marks a class/field/method as deprecated
|
||||
Deprecated {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4, // 0
|
||||
},
|
||||
Deprecated,
|
||||
/// Can be on `ClassFile`, `FieldInfo`,or `MethodInfo`. Contains all Runtime visible annotations
|
||||
RuntimeVisibleAnnotations {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
num_annotations: u2,
|
||||
annotations: Vec<Annotation>,
|
||||
},
|
||||
/// Same as `RuntimeVisibleAnnotations`, but invisible to reflection
|
||||
RuntimeInvisibleAnnotations {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
num_annotations: u2,
|
||||
annotations: Vec<Annotation>,
|
||||
},
|
||||
/// Only on `MethodInfo`, parameter annotations visible during runtime
|
||||
RuntimeVisibleParameterAnnotations {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
num_parameters: u1,
|
||||
parameter_annotations: Vec<ParameterAnnotation>,
|
||||
},
|
||||
/// Same as `RuntimeVisibleParameterAnnotations`, but invisible to reflection
|
||||
RuntimeInvisibleParameterAnnotations {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
num_parameters: u1,
|
||||
parameter_annotations: Vec<ParameterAnnotation>,
|
||||
},
|
||||
/// Only on `MethodInfo`, on those representing elements of annotation types, the default value of the element
|
||||
AnnotationDefault {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
default_value: AnnotationElementValue,
|
||||
},
|
||||
/// Only on `ClassFile`. Records bootstrap method specifiers for `invokedynamic`
|
||||
BootstrapMethods {
|
||||
attribute_name_index: u2,
|
||||
attribute_length: u4,
|
||||
num_bootstrap_methods: u2,
|
||||
bootstrap_methods: Vec<BootstrapMethod>,
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue