diff --git a/.gitignore b/.gitignore index ea8c4bf..023c447 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ +.idea +*.iml + /target + +*.class \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index d4e3fca..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Datasource local storage ignored files -/../../../../../../../:\Users\nilsh\CLionProjects\rust\coldsquare\.idea/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/coldsquare.iml b/.idea/coldsquare.iml deleted file mode 100644 index c254557..0000000 --- a/.idea/coldsquare.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml deleted file mode 100644 index cd711a0..0000000 --- a/.idea/discord.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 461fec0..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 5f77177..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/execute/model.rs b/src/execute/model.rs index 5a5990e..66606be 100644 --- a/src/execute/model.rs +++ b/src/execute/model.rs @@ -4,9 +4,7 @@ pub struct OperandStack { impl OperandStack { pub fn new() -> OperandStack { - OperandStack { - vec: vec![], - } + OperandStack { vec: vec![] } } pub fn pop(&mut self) -> u32 { @@ -19,19 +17,17 @@ impl OperandStack { pub fn swap(&mut self) { let len = self.vec.len(); - self.vec.swap(len- 1, len - 2); + self.vec.swap(len - 1, len - 2); } } pub struct LocalVariables { - vec: Vec + vec: Vec, } impl LocalVariables { pub fn new(size: usize) -> LocalVariables { - LocalVariables { - vec: vec![0; size] - } + LocalVariables { vec: vec![0; size] } } pub fn store(&mut self, address: u8, value: u32) { @@ -49,12 +45,11 @@ impl LocalVariables { pub fn load2(&self, address: u8) -> (u32, u32) { (self.vec[address as usize], self.vec[address as usize + 1]) } - } #[cfg(test)] mod tests { - use crate::model::{LocalVariables, OperandStack}; + use crate::execute::model::{LocalVariables, OperandStack}; #[test] fn operand_stack() { @@ -84,4 +79,4 @@ mod tests { assert_eq!(vars.load(3), 100); assert_eq!(vars.load(4), 466); } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 14367f3..7948beb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,8 @@ +use crate::parse::{ClassFile, ParseErr}; + +mod execute; mod parse; -mod execute; \ No newline at end of file + +pub fn parse_class_file(file: Vec) -> Result { + parse::parse_class_file(file) +} diff --git a/src/main.rs b/src/main.rs index e7a11a9..18be829 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,10 @@ +use coldsquare::parse_class_file; + fn main() { - println!("Hello, world!"); + let file = "primeNumberChecker.class"; + let file = std::fs::read(file).unwrap(); + + let class_file = parse_class_file(file).unwrap(); + + println!("{:?}", class_file); } diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 3ced475..7ce4d69 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -1,14 +1,22 @@ -use crate::parse::model::{u1, u2, u4, ClassFile, CpInfo}; - mod model; +pub use model::*; +use std::path::Prefix::Verbatim; -struct ParseErr; +#[derive(Debug)] +pub struct ParseErr; + +pub type Result = std::result::Result; struct Data { data: Vec, pointer: usize, } +pub fn parse_class_file(data: Vec) -> Result { + let mut data = Data { data, pointer: 0 }; + ClassFile::parse(&mut data) +} + impl From> for Data { fn from(data: Vec) -> Self { Self { data, pointer: 0 } @@ -16,67 +24,422 @@ impl From> for Data { } impl Data { - fn u1(&mut self) -> Result { + fn u1(&mut self) -> Result { let item = self.data.get(self.pointer).cloned(); self.pointer += 1; item.ok_or(ParseErr) } - fn u2(&mut self) -> Result { - Ok(((self.u1()? as u2) << 8) | self.u1() as u2) + fn u2(&mut self) -> Result { + Ok(((self.u1()? as u2) << 8) | self.u1()? as u2) } - fn u4(&mut self) -> Result { - Ok(((self.u2()? as u4) << 16) | self.u2() as u4) + fn u4(&mut self) -> Result { + Ok(((self.u2()? as u4) << 16) | self.u2()? as u4) } - fn last_u1(&mut self) -> Result { + fn last_u1(&self) -> Result { self.data.get(self.pointer - 1).cloned().ok_or(ParseErr) } - fn last_u2(&mut self) -> Result { - let last2u1 = self.data.get(self.pointer - 2).cloned().ok_or(ParseErr); - Ok(((self.last_u1()? as u2) << 8) | last2u1 as u2) + fn last_u2(&self) -> Result { + let last2u1 = self.data.get(self.pointer - 2).cloned().ok_or(ParseErr)?; + Ok(((last2u1 as u2) << 8) | self.last_u1()? as u2) + } + + fn last_u4(&self) -> Result { + let last2u1 = self.data.get(self.pointer - 3).cloned().ok_or(ParseErr)?; + let last3u1 = self.data.get(self.pointer - 4).cloned().ok_or(ParseErr)?; + Ok(((last3u1 as u4) << 24) | ((last2u1 as u4) << 16) | self.last_u2()? as u4) } } pub trait Parse { - fn parse(data: &mut Data) -> Result; + fn parse(data: &mut Data) -> Result + where + Self: Sized; } pub trait ParseVec { - fn parse_vec(data: &mut Data, len: usize) -> Result; -} - -impl Parse for ClassFile { - fn parse(data: &mut Data) -> Result { - Ok(Self { - magic: data.u4()?, - minor_version: data.u2()?, - major_version: data.u2()?, - constant_pool_count: data.u2()?, - constant_pool: Vec::parse_vec::(data, data.last_u2() as usize)?, - access_flags: data.u2()?, - this_class: data.u2()?, - super_class: data.u2()?, - interfaces_count: data.u2()?, - interfaces: vec![], - fields_count: 0, - fields: vec![], - method_count: 0, - methods: vec![], - attributes_count: 0, - attributes: vec![], - }) - } + fn parse_vec(data: &mut Data, len: usize) -> Result + where + Self: Sized; } impl ParseVec for Vec { - fn parse_vec(data: &mut Data, len: usize) -> Result { + fn parse_vec(data: &mut Data, len: usize) -> Result { let mut vec = Vec::with_capacity(len); - for i in 0..len { + for _ in 0..len { vec.push(T::parse(data)?); } Ok(vec) } } + +macro_rules! parse_primitive { + ($value:ident) => { + impl Parse for $value { + fn parse(data: &mut Data) -> Result + where + Self: Sized, + { + data.$value() + } + } + }; +} + +parse_primitive!(u1); +parse_primitive!(u2); +parse_primitive!(u4); + +impl Parse for ClassFile { + fn parse(data: &mut Data) -> Result { + Ok(Self { + magic: data.u4()?, + minor_version: data.u2()?, + major_version: data.u2()?, + constant_pool_count: data.u2()?, + constant_pool: Vec::parse_vec(data, data.last_u2()? as usize)?, + access_flags: data.u2()?, + this_class: data.u2()?, + super_class: data.u2()?, + interfaces_count: data.u2()?, + interfaces: Vec::parse_vec(data, data.last_u2()? as usize)?, + fields_count: data.u2()?, + fields: Vec::parse_vec(data, data.last_u2()? as usize)?, + method_count: data.u2()?, + methods: Vec::parse_vec(data, data.last_u2()? as usize)?, + attributes_count: data.u2()?, + attributes: Vec::parse_vec(data, data.last_u2()? as usize)?, + }) + } +} + +impl Parse for CpInfo { + fn parse(data: &mut Data) -> Result { + let tag = data.u1()?; + + Ok(match tag { + 7 => Self::Class { + tag, + name_index: data.u2()?, + }, + 9 => Self::Fieldref { + tag, + class_index: data.u2()?, + name_and_type_index: data.u2()?, + }, + 10 => Self::Methodref { + tag, + class_index: data.u2()?, + name_and_type_index: data.u2()?, + }, + 11 => Self::InterfaceMethodref { + tag, + class_index: data.u2()?, + name_and_type_index: data.u2()?, + }, + 8 => Self::String { + tag, + string_index: data.u2()?, + }, + 3 => Self::Integer { + tag, + bytes: data.u4()?, + }, + 4 => Self::Float { + tag, + bytes: data.u4()?, + }, + 5 => Self::Long { + tag, + high_bytes: data.u4()?, + low_bytes: data.u4()?, + }, + 6 => Self::Double { + tag, + high_bytes: data.u4()?, + low_bytes: data.u4()?, + }, + 12 => Self::NameAndType { + tag, + name_index: data.u2()?, + descriptor_index: data.u2()?, + }, + 1 => Self::Utf8 { + tag, + length: data.u2()?, + bytes: Vec::parse_vec(data, data.last_u2()? as usize)?, + }, + 15 => Self::MethodHandle { + tag, + reference_kind: data.u1()?, + reference_index: data.u2()?, + }, + 16 => Self::MethodType { + tag, + descriptor_index: data.u2()?, + }, + 18 => Self::InvokeDynamic { + tag, + bootstrap_method_attr_index: data.u2()?, + name_and_type_index: data.u2()?, + }, + _ => Err(ParseErr)?, + }) + } +} + +impl Parse for FieldInfo { + fn parse(data: &mut Data) -> Result { + Ok(Self { + access_flags: data.u2()?, + name_index: data.u2()?, + descriptor_index: data.u2()?, + attributes_count: data.u2()?, + attributes: Vec::parse_vec(data, data.last_u2()? as usize)?, + }) + } +} + +impl Parse for MethodInfo { + fn parse(data: &mut Data) -> Result { + Ok(Self { + access_flags: data.u2()?, + name_index: data.u2()?, + descriptor_index: data.u2()?, + attributes_count: data.u2()?, + attributes: Vec::parse_vec(data, data.last_u2()? as usize)?, + }) + } +} + +impl Parse for Attribute { + fn parse(data: &mut Data) -> Result { + Ok(Self { + attribute_name_index: data.u2()?, + attribute_length: data.u4()?, + attribute_content: Vec::parse_vec(data, data.last_u4()? as usize)?, + }) + } +} + +impl Parse for AttributeCodeException { + fn parse(data: &mut Data) -> Result { + Ok(Self { + start_pc: data.last_u2()?, + end_pc: data.last_u2()?, + handler_pc: data.last_u2()?, + catch_type: data.last_u2()?, + }) + } +} + +impl Parse for StackMapFrame { + fn parse(data: &mut Data) -> Result { + let frame_type = data.u1()?; + + Ok(match frame_type { + 0..=63 => Self::SameFrame { frame_type }, + 64..=127 => Self::SameLocals1StackItemFrame { + frame_type, + stack: VerificationTypeInfo::parse(data)?, + }, + 247 => Self::SameLocals1StackItemFrameExtended { + frame_type, + offset_delta: data.u2()?, + stack: VerificationTypeInfo::parse(data)?, + }, + 246..=250 => Self::ChopFrame { + frame_type, + offset_delta: data.u2()?, + }, + 251 => Self::SameFrameExtended { + frame_type, + offset_delta: data.u2()?, + }, + 252..=254 => Self::AppendFrame { + frame_type, + offset_delta: data.u2()?, + locals: Vec::parse_vec(data, data.last_u2()? as usize)?, + }, + 255 => Self::FullFrame { + frame_type, + offset_delta: data.u2()?, + number_of_locals: data.u2()?, + locals: Vec::parse_vec(data, data.last_u2()? as usize)?, + number_of_stack_items: data.u2()?, + stack: Vec::parse_vec(data, data.last_u2()? as usize)?, + }, + _ => Err(ParseErr)?, + }) + } +} + +impl Parse for VerificationTypeInfo { + fn parse(data: &mut Data) -> Result + where + Self: Sized, + { + let tag = data.u1()?; + Ok(match tag { + 0 => Self::Top { tag }, + 1 => Self::Integer { tag }, + 2 => Self::Float { tag }, + 4 => Self::Long { tag }, + 3 => Self::Double { tag }, + 5 => Self::Null { tag }, + 6 => Self::UninitializedThis { tag }, + 7 => Self::Object { + tag, + cpool_index: data.u2()?, + }, + 8 => Self::Uninitialized { + tag, + offset: data.u2()?, + }, + _ => Err(ParseErr)?, + }) + } +} + +impl Parse for AttributeInnerClass { + fn parse(data: &mut Data) -> Result { + Ok(Self { + inner_class_info_index: data.u2()?, + outer_class_info_index: data.u2()?, + inner_class_name_index: data.u2()?, + inner_class_access_flags: data.u2()?, + }) + } +} + +impl Parse for AttributeLineNumber { + fn parse(data: &mut Data) -> Result { + Ok(Self { + start_pc: data.u2()?, + line_number: data.u2()?, + }) + } +} + +impl Parse for AttributeLocalVariableTable { + fn parse(data: &mut Data) -> Result { + Ok(Self { + start_pc: data.u2()?, + length: data.u2()?, + name_index: data.u2()?, + descriptor_or_signature_index: data.u2()?, + index: data.u2()?, + }) + } +} + +impl Parse for Annotation { + fn parse(data: &mut Data) -> Result { + Ok(Self { + type_index: data.u2()?, + num_element_value_pairs: data.u2()?, + element_value_pairs: Vec::parse_vec(data, data.last_u2()? as usize)?, + }) + } +} + +impl Parse for AnnotationElementValuePair { + fn parse(data: &mut Data) -> Result { + Ok(Self { + element_name_index: data.u2()?, + element_name_name: AnnotationElementValue::parse(data)?, + }) + } +} + +impl Parse for AnnotationElementValue { + fn parse(data: &mut Data) -> Result { + Ok(Self { + tag: data.u1()?, + value: AnnotationElementValueValue::parse(data)?, + }) + } +} + +impl Parse for AnnotationElementValueValue { + fn parse(data: &mut Data) -> Result { + let tag = data.last_u1()? as char; + Ok(match tag { + 'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's' => { + Self::ConstValueIndex { index: data.u2()? } + } + 'e' => Self::EnumConstValue { + type_name_index: data.u2()?, + const_name_index: data.u2()?, + }, + 'c' => Self::ClassInfoIndex { index: data.u2()? }, + '@' => Self::AnnotationValue { + annotation: Box::new(Annotation::parse(data)?), + }, + '[' => Self::ArrayValue { + num_values: data.u2()?, + values: Vec::parse_vec(data, data.last_u2()? as usize)?, + }, + _ => Err(ParseErr)?, + }) + } +} + +impl Parse for ParameterAnnotation { + fn parse(data: &mut Data) -> Result { + Ok(Self { + num_annotations: data.u2()?, + annotations: Vec::parse_vec(data, data.last_u2()? as usize)?, + }) + } +} + +impl Parse for BootstrapMethod { + fn parse(data: &mut Data) -> Result { + Ok(Self { + bootstrap_method_ref: data.u2()?, + num_bootstrap_arguments: data.u2()?, + bootstrap_arguments: Vec::parse_vec(data, data.last_u2()? as usize)?, + }) + } +} + +#[cfg(test)] +mod test { + use crate::parse::Data; + + #[test] + fn data_u1() { + let mut data = Data { + data: vec![0xff, 0x00], + pointer: 0, + }; + assert_eq!(data.u1().unwrap(), 0xff); + assert_eq!(data.u1().unwrap(), 0x00); + assert_eq!(data.last_u1().unwrap(), 0x00); + } + + #[test] + fn data_u2() { + let mut data = Data { + data: vec![0xff, 0x33, 0x11, 0x00], + pointer: 0, + }; + assert_eq!(data.u2().unwrap(), 0xff33); + assert_eq!(data.u2().unwrap(), 0x1100); + assert_eq!(data.last_u2().unwrap(), 0x1100); + } + + #[test] + fn data_u4() { + let mut data = Data { + data: vec![0xff, 0x33, 0x11, 0x00], + pointer: 0, + }; + assert_eq!(data.u4().unwrap(), 0xff331100); + assert_eq!(data.last_u4().unwrap(), 0xff331100); + } +} diff --git a/src/parse/model.rs b/src/parse/model.rs index e52e30d..12666a5 100644 --- a/src/parse/model.rs +++ b/src/parse/model.rs @@ -14,44 +14,46 @@ pub type u4 = u32; /// /// # Represents a .class file /// +#[derive(Debug, Clone, Hash)] pub struct ClassFile { /// Magic number identifying the format (= 0xCAFEBABE) - pub(crate) magic: u4, + pub magic: u4, /// The version of the class file (.X) - pub(crate) minor_version: u2, + pub minor_version: u2, /// The version of the class file (X.) - pub(crate) major_version: u2, + pub major_version: u2, /// Number of entries in the constant pool + 1 - pub(crate) constant_pool_count: u2, + pub constant_pool_count: u2, /// The constant pool. Indexed from 1 to constant_pool_count - 1 - pub(crate) constant_pool: Vec, + pub constant_pool: Vec, /// Mask of `ClassAccessFlag` used to denote access permissions - pub(crate) access_flags: u2, + pub access_flags: u2, /// A valid index into the `constant_pool` table. The entry must be a `ConstantClassInfo` - pub(crate) this_class: u2, + pub this_class: u2, /// Zero or a valid index into the `constant_pool` table - pub(crate) super_class: u2, + pub super_class: u2, /// The number if direct superinterfaces of this class or interface type - pub(crate) interfaces_count: u2, + pub interfaces_count: u2, /// Each entry must be a valid index into the `constant_pool` table. The entry must be a `ConstantClassInfo` - pub(crate) interfaces: Vec, + pub interfaces: Vec, /// The number of fields in the `fields` table - pub(crate) fields_count: u2, + pub fields_count: u2, /// All fields of the class. Contains only fields of the class itself - pub(crate) fields: Vec, + pub fields: Vec, /// The number of methods in `methods` - pub(crate) method_count: u2, + pub method_count: u2, /// All methods of the class. If it's neither Native nor Abstract, the implementation has to be provided too - pub(crate) methods: Vec, + pub methods: Vec, /// The number of attributes in `attributes` - pub(crate) attributes_count: u2, + pub attributes_count: u2, /// All attributes of the class - pub(crate) attributes: Vec, + pub attributes: Vec, } /// A constant from the constant pool /// May have indices back to the constant pool, with expected types /// _index: A valid index into the `constant_pool` table. +#[derive(Debug, Clone, Hash)] pub enum CpInfo { Class { tag: u1, // 7 @@ -139,7 +141,7 @@ pub enum CpInfo { descriptor_index: u2, }, InvokeDynamic { - tag: u1, + tag: u1, // 18 /// Must be a valid index into the `bootstrap_methods` array of the bootstrap method table of this class fiel bootstrap_method_attr_index: u2, /// Entry must `NameAndType` @@ -148,26 +150,36 @@ pub enum CpInfo { } /// Information about a field +#[derive(Debug, Clone, Hash)] pub struct FieldInfo { - access_flags: u2, - name_index: u2, - descriptor_index: u2, - attributes_count: u2, - attributes: Vec, + pub access_flags: u2, + pub name_index: u2, + pub descriptor_index: u2, + pub attributes_count: u2, + pub attributes: Vec, } /// Information about a method +#[derive(Debug, Clone, Hash)] pub struct MethodInfo { /// Mask of `MethodAccessFlag` used to denote access permissions - access_flags: u2, + pub access_flags: u2, /// Index to the `constant_pool` of the method name, must be `Utf8` - name_index: u2, + pub name_index: u2, /// Index to the `constant_pool` of the method descriptor, must be `Utf8` - descriptor_index: u2, + pub descriptor_index: u2, /// The amount of attributes for this method - attributes_count: u2, + pub attributes_count: u2, /// The attributes for this method - attributes: Vec, + pub attributes: Vec, +} + +/// See `AttributeInfo` +#[derive(Debug, Clone, Hash)] +pub struct Attribute { + pub attribute_name_index: u2, + pub attribute_length: u4, + pub attribute_content: Vec, } /// Information about an attribute @@ -176,6 +188,8 @@ pub struct MethodInfo { /// `attribute_length`: The length of the subsequent bytes, does not include the first 6 /// /// _index: Index to the `constant_pool` table of any type +#[derive(Debug, Clone, Hash)] +#[allow(dead_code)] // todo yeah lol pub enum AttributeInfo { /// Only on fields, the constant value of that field ConstantValue { @@ -202,7 +216,7 @@ pub enum AttributeInfo { exception_table: Vec, attributes_count: u2, /// The attributes of the code - attributes: Vec, + attributes: Vec, }, /// Only on the `Code` attribute, used for verification /// May be implicit on version >= 50.0, with no entries @@ -336,22 +350,24 @@ pub enum AttributeInfo { } /// An exception handler in the JVM bytecode array +#[derive(Debug, Clone, Hash)] pub struct AttributeCodeException { /// The ranges in the code in which the handler is active. Must be a valid index into the code array. /// The `start_pc` is inclusive - start_pc: u2, + pub start_pc: u2, /// The ranges in the code in which the handler is active. Must be a valid index into the code array or the length. /// The `end_pc` is exclusive - end_pc: u2, + pub end_pc: u2, /// The start of the exception handler, must be a valid index into the code array at an opcode instruction - handler_pc: u2, + pub handler_pc: u2, /// If the catch type is nonzero, it must be a valid index into the `constant_pool`, must be a `Class` /// Zero means it catches all Exceptions, this is usually for `finally` - catch_type: u2, + pub catch_type: u2, } /// Specifies the type state at a particular bytecode offset /// Has a offset_delta, the offset is calculated by adding offset_delta + 1 to the previous offset +#[derive(Debug, Clone, Hash)] pub enum StackMapFrame { /// Exactly the same locals as the previous frame and zero stack items, offset_delta is frame_type SameFrame { @@ -364,7 +380,7 @@ pub enum StackMapFrame { }, /// Exactly the same locals as the previous frame and 1 stack item, offset_delta is given explicitly SameLocals1StackItemFrameExtended { - frame_type: u1, // 257 + frame_type: u1, // 247 offset_delta: u2, stack: VerificationTypeInfo, }, @@ -397,6 +413,7 @@ pub enum StackMapFrame { } /// A stack value/local variable type `StackMapFrame` +#[derive(Debug, Clone, Hash)] pub enum VerificationTypeInfo { Top { tag: u1, // 0 @@ -431,64 +448,71 @@ pub enum VerificationTypeInfo { } /// A struct for the `AttributeInfo::InnerClasses` +#[derive(Debug, Clone, Hash)] pub struct AttributeInnerClass { /// Must be a `Class` - inner_class_info_index: u2, + pub inner_class_info_index: u2, /// Must be 0 or a `Class` - outer_class_info_index: u2, + pub outer_class_info_index: u2, /// Must be 0 or `Utf8` - inner_class_name_index: u2, + pub inner_class_name_index: u2, /// Must be a mask of `InnerClassAccessFlags` - inner_class_access_flags: u2, + pub inner_class_access_flags: u2, } /// Line number information for `AttributeInfo::LineNumberTable` +#[derive(Debug, Clone, Hash)] pub struct AttributeLineNumber { /// Index into the code array where a new line in the source begins - start_pc: u2, + pub start_pc: u2, /// The line number in the source file - line_number: u2, + pub line_number: u2, } /// Local variable information for `AttributeInfo::LocalVariableTable` and `AttributeInfo::LocalVariableTypeTable` +#[derive(Debug, Clone, Hash)] pub struct AttributeLocalVariableTable { /// The local variable must have a value between `start_pc` and `start_pc + length`. Must be a valid opcode - start_pc: u2, + pub start_pc: u2, /// The local variable must have a value between `start_pc` and `start_pc + length` - length: u2, + pub length: u2, /// Must be `Utf8` - name_index: u2, + pub name_index: u2, /// Must be `Utf8`, field descriptor or field signature encoding the type - descriptor_or_signature_index: u2, + pub descriptor_or_signature_index: u2, /// The variable must be at `index` in the local variable array - index: u2, + pub index: u2, } /// A runtime-visible annotation to the program +#[derive(Debug, Clone, Hash)] pub struct Annotation { /// Must be `Utf8` - type_index: u2, - num_element_value_pairs: u2, - element_value_pairs: Vec, + pub type_index: u2, + pub num_element_value_pairs: u2, + pub element_value_pairs: Vec, } // these type names have just become java at this point. no shame. /// A element-value pair in the `Annotation` +#[derive(Debug, Clone, Hash)] pub struct AnnotationElementValuePair { /// Must be `Utf8` - element_name_index: u2, - element_name_name: AnnotationElementValue, + pub element_name_index: u2, + pub element_name_name: AnnotationElementValue, } /// The value of an `AnnotationElementValuePair` +#[derive(Debug, Clone, Hash)] pub struct AnnotationElementValue { /// B, C, D, F, I, J, S, Z or s, e, c, @, - tag: u1, - value: AnnotationElementValueValue, + pub tag: u1, + pub value: AnnotationElementValueValue, } /// The value of a `AnnotationElementValue` +#[derive(Debug, Clone, Hash)] pub enum AnnotationElementValueValue { /// If the tag is B, C, D, F, I, J, S, Z, or s. ConstValueIndex { @@ -520,24 +544,27 @@ pub enum AnnotationElementValueValue { } /// Used in `AttributeInfo::RuntimeVisibleParameterAnnotations` +#[derive(Debug, Clone, Hash)] pub struct ParameterAnnotation { - num_annotations: u2, - annotations: Vec, + pub num_annotations: u2, + pub annotations: Vec, } /// Used in `AttributeInfo::BootstrapMethods ` +#[derive(Debug, Clone, Hash)] pub struct BootstrapMethod { /// Must be a `MethodHandle` - bootstrap_method_ref: u2, - num_bootstrap_arguments: u2, + pub bootstrap_method_ref: u2, + pub num_bootstrap_arguments: u2, /// Each argument is a cpool entry. The constants must be `String, Class, Integer, Long, Float, Double, MethodHandle, or MethodType` - bootstrap_arguments: Vec, + pub bootstrap_arguments: Vec, } /////// Access Flags /// Access Flags of a class #[repr(u16)] +#[derive(Debug, Clone, Hash)] pub enum ClassAccessFlag { /// Declared public; may be accessed from outside its package. Public = 0x0001, @@ -559,6 +586,7 @@ pub enum ClassAccessFlag { /// Access Flags of a method #[repr(u16)] +#[derive(Debug, Clone, Hash)] pub enum MethodAccessFlag { // Declared public; may be accessed from outside its package. PUBLIC = 0x0001, @@ -588,6 +616,7 @@ pub enum MethodAccessFlag { /// Access flags for an inner class #[repr(u16)] +#[derive(Debug, Clone, Hash)] pub enum InnerClassAccessFlags { /// Marked or implicitly public in source. PUBLIC = 0x0001, @@ -613,6 +642,7 @@ pub enum InnerClassAccessFlags { /// Access flags for a field #[repr(u16)] +#[derive(Debug, Clone, Hash)] pub enum FieldAccessFlags { /// Declared public; may be accessed from outside its package. PUBLIC = 0x0001,