diff --git a/Cargo.toml b/Cargo.toml index e644fdd..a768019 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dependencies] +[dependencies] \ No newline at end of file diff --git a/Dummy.class b/Dummy.class index fff6eba..17b5c76 100644 Binary files a/Dummy.class and b/Dummy.class differ diff --git a/Dummy.java b/Dummy.java index d83a15a..0c9c2f9 100644 --- a/Dummy.java +++ b/Dummy.java @@ -2,6 +2,9 @@ package dummy; public class Dummy { + private final static String constant = "meh"; + private final int integer = 57; + private final String name; public Dummy(String name) { diff --git a/src/io.rs b/src/io.rs new file mode 100644 index 0000000..be583c5 --- /dev/null +++ b/src/io.rs @@ -0,0 +1,23 @@ +pub(crate) fn read_u16(data: &[u8], pos: usize) -> u16 { + u16::from_be_bytes(data[pos..pos + 2].try_into().expect("slice with incorrect length")) +} + +pub(crate) fn read_i32(data: &[u8], pos: usize) -> i32 { + i32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length")) +} + +pub(crate) fn read_u32(data: &[u8], pos: usize) -> u32 { + u32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length")) +} + +pub(crate) fn read_f32(data: &[u8], pos: usize) -> f32 { + f32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length")) +} + +pub(crate) fn read_i64(data: &[u8], pos: usize) -> i64 { + i64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length")) +} + +pub(crate) fn read_f64(data: &[u8], pos: usize) -> f64 { + f64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length")) +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6ed50c8..12eb869 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,56 +1,63 @@ pub mod types; +mod io; use std::rc::Rc; -use crate::types::{Attribute, Class, Field, Method}; +use crate::io::{read_f32, read_f64, read_i32, read_i64, read_u16, read_u32}; +use crate::types::{AttributeType, Class, MethodCode, Exception, Field, Method}; pub fn get_class(bytecode: Vec) -> Option { check_magic(&bytecode); - let constant_pool_count = get_u16(&bytecode, 8); + let constant_pool_count = read_u16(&bytecode, 8); let mut index = 10; let mut constant_pool: Vec = vec![]; - for _ in 0..constant_pool_count - 1 { - constant_pool.push(read_constant_pool_entry(&mut index, &bytecode)); + for cp_index in 0..constant_pool_count - 1 { + constant_pool.push(read_constant_pool_entry((cp_index + 1) as usize, &mut index, &bytecode)); } let constant_pool = Rc::new(constant_pool); - let access_flags = get_u16(&bytecode, index); - let this_class = get_u16(&bytecode, index + 2); - let super_class = get_u16(&bytecode, index + 4); + let access_flags = read_u16(&bytecode, index); + let this_class = read_u16(&bytecode, index + 2); + let super_class = read_u16(&bytecode, index + 4); - let interfaces_count = get_u16(&bytecode, index + 6); + let interfaces_count = read_u16(&bytecode, index + 6); index += 8; let mut interfaces = vec![]; for _ in 0..interfaces_count { - interfaces.push(get_u16(&bytecode, index)); + interfaces.push(read_u16(&bytecode, index)); index += 2; } - let fields_count = get_u16(&bytecode, index); + let fields_count = read_u16(&bytecode, index); index += 2; let mut fields = vec![]; for _ in 0..fields_count { fields.push(read_field(constant_pool.clone(), &mut index, &bytecode)); } - let methods_count = get_u16(&bytecode, index); + let methods_count = read_u16(&bytecode, index); index += 2; let mut methods = vec![]; for _ in 0..methods_count { methods.push(read_method(constant_pool.clone(), &mut index, &bytecode)); } - let attributes_count = get_u16(&bytecode, index); + let attributes_count = read_u16(&bytecode, index); index += 2; let mut attributes = vec![]; for _ in 0..attributes_count { - attributes.push(read_attribute(constant_pool.clone(), &bytecode, &mut index)); + let some = read_attribute(constant_pool.clone(), &bytecode, &mut index); + if let Some(att) = some { + attributes.push(att); + } else { + panic!(); // bug/not-implemented + } } Some(Class { - minor_version: get_u16(&bytecode, 4), - major_version: get_u16(&bytecode, 6), + minor_version: read_u16(&bytecode, 4), + major_version: read_u16(&bytecode, 6), constant_pool, access_flags, this_class, @@ -68,68 +75,68 @@ fn check_magic(bytecode: &[u8]) { } } -fn read_constant_pool_entry(index: &mut usize, bytecode: &[u8]) -> CpEntry { +fn read_constant_pool_entry(cp_index: usize, index: &mut usize, bytecode: &[u8]) -> CpEntry { let tag = bytecode[*index]; match tag { 1 => { - let len = get_u16(bytecode, *index + 1) as usize; + let len = read_u16(bytecode, *index + 1) as usize; let utf: Vec = Vec::from(&bytecode[*index + 3..*index + 3 + len]); *index += len + 3; - CpEntry::Utf8(String::from_utf8(utf).unwrap()) + CpEntry::Utf8(cp_index, String::from_utf8(utf).unwrap()) } 3 => { - let value = get_i32(bytecode, *index + 1); + let value = read_i32(bytecode, *index + 1); *index += 5; - CpEntry::Integer(value) + CpEntry::Integer(cp_index, value) } 4 => { - let value = get_f32(bytecode, *index + 1); + let value = read_f32(bytecode, *index + 1); *index += 5; - CpEntry::Float(value) + CpEntry::Float(cp_index, value) } 5 => { - let value = get_i64(bytecode, *index + 1); + let value = read_i64(bytecode, *index + 1); *index += 9; - CpEntry::Long(value) + CpEntry::Long(cp_index, value) } 6 => { - let value = get_f64(bytecode, *index + 1); + let value = read_f64(bytecode, *index + 1); *index += 9; - CpEntry::Double(value) + CpEntry::Double(cp_index, value) } 7 => { - let name_index = get_u16(bytecode, *index + 1); + let name_index = read_u16(bytecode, *index + 1); *index += 3; - CpEntry::ClassRef(name_index) + CpEntry::ClassRef(cp_index, name_index) } 8 => { - let string_index = get_u16(bytecode, *index + 1); + let string_index = read_u16(bytecode, *index + 1); *index += 3; - CpEntry::StringRef(string_index) + CpEntry::StringRef(cp_index, string_index) } 9 => { - let class_index = get_u16(bytecode, *index + 1); - let name_and_type_index = get_u16(bytecode, *index + 3); + let class_index = read_u16(bytecode, *index + 1); + let name_and_type_index = read_u16(bytecode, *index + 3); *index += 5; - CpEntry::Fieldref(class_index, name_and_type_index) + CpEntry::Fieldref(cp_index, class_index, name_and_type_index) } 10 => { - let class_index = get_u16(bytecode, *index + 1); - let name_and_type_index = get_u16(bytecode, *index + 3); + let class_index = read_u16(bytecode, *index + 1); + let name_and_type_index = read_u16(bytecode, *index + 3); *index += 5; - CpEntry::MethodRef(class_index, name_and_type_index) + CpEntry::MethodRef(cp_index, class_index, name_and_type_index) } 11 => { - let class_index = get_u16(bytecode, *index + 1); - let name_and_type_index = get_u16(bytecode, *index + 3); + let class_index = read_u16(bytecode, *index + 1); + let name_and_type_index = read_u16(bytecode, *index + 3); *index += 5; - CpEntry::InterfaceMethodref(class_index, name_and_type_index) + CpEntry::InterfaceMethodref(cp_index, class_index, name_and_type_index) } 12 => { - let name_index = get_u16(bytecode, *index + 1) as usize; - let descriptor_index = get_u16(bytecode, *index + 3) as usize; + let name_index = read_u16(bytecode, *index + 1) as usize; + let descriptor_index = read_u16(bytecode, *index + 3) as usize; *index += 5; - CpEntry::NameAndType(name_index, descriptor_index) + CpEntry::NameAndType(cp_index, name_index, descriptor_index) } // 15 MethodHandle, // 16 MethodType, @@ -142,14 +149,18 @@ fn read_constant_pool_entry(index: &mut usize, bytecode: &[u8]) -> CpEntry { } fn read_field(constant_pool: Rc>, index: &mut usize, bytecode: &[u8]) -> Field { - let access_flags = get_u16(bytecode, *index); - let name_index = get_u16(bytecode, *index + 2) as usize; - let descriptor_index = get_u16(bytecode, *index + 4) as usize; - let attributes_count = get_u16(bytecode, *index + 6); + let access_flags = read_u16(bytecode, *index); + let name_index = read_u16(bytecode, *index + 2) as usize; + let descriptor_index = read_u16(bytecode, *index + 4) as usize; + let attributes_count = read_u16(bytecode, *index + 6); *index += 8; let mut attributes = vec![]; for _ in 0..attributes_count { - attributes.push(read_attribute(bytecode, index)); + if let Some(att) = read_attribute(constant_pool.clone(), bytecode, index) { + attributes.push(att); + } else { + panic!(); // bug/not-implemented + } } Field::new( constant_pool, @@ -161,16 +172,20 @@ fn read_field(constant_pool: Rc>, index: &mut usize, bytecode: &[u8 } fn read_method(constant_pool: Rc>, index: &mut usize, bytecode: &[u8]) -> Method { - let access_flags = get_u16(bytecode, *index); - let name_index = get_u16(bytecode, *index + 2) as usize; - let descriptor_index = get_u16(bytecode, *index + 4) as usize; - let attributes_count = get_u16(bytecode, *index + 6); + let access_flags = read_u16(bytecode, *index); + let name_index = read_u16(bytecode, *index + 2) as usize; + let descriptor_index = read_u16(bytecode, *index + 4) as usize; + let attributes_count = read_u16(bytecode, *index + 6); *index += 8; + let mut attributes = vec![]; for _ in 0..attributes_count { - attributes.push(read_attribute(bytecode, index)); + if let Some(att) = read_attribute(constant_pool.clone(), bytecode, index) { + attributes.push(att); + } } - Method::new ( + + Method::new( constant_pool, access_flags, name_index, @@ -179,60 +194,64 @@ fn read_method(constant_pool: Rc>, index: &mut usize, bytecode: &[u ) } -fn read_attribute(constant_pool: Rc>, bytecode: &[u8], index: &mut usize) -> Attribute { - let attribute_name_index = get_u16(bytecode, *index) as usize; +fn read_attribute(constant_pool: Rc>, bytecode: &[u8], index: &mut usize) -> Option { + let attribute_name_index = read_u16(bytecode, *index) as usize; *index += 2; let attribute_length = read_u32(bytecode, *index) as usize; *index += 4; let info: Vec = Vec::from(&bytecode[*index..*index + attribute_length]); *index += attribute_length; - Attribute { - attribute_name_index, - info, + + if let CpEntry::Utf8(_, s) = &constant_pool[attribute_name_index - 1] { + // println!("{}", s); + return match s.as_str() { + "ConstantValue" => { + assert_eq!(info.len(), 2); + Some(AttributeType::ConstantValue(read_u16(&info, 0))) + } + "Code" => { + let max_stack = read_u16(&info, 0); + let max_locals = read_u16(&info, 2); + let code_length = read_u32(&info, 4) as usize; + let code = Vec::from(&info[8..8 + code_length]); + let exception_table_length = read_u16(&info, 8 + code_length) as usize; + + let mut code_index = 10 + code_length; + let mut exception_table = vec![]; + for _ in 0..exception_table_length { + exception_table.push(Exception::read(&info, code_index)); + code_index += 8; + } + let attribute_count = read_u16(&info, code_index); + code_index += 2; + let mut code_attributes = vec![]; + for _ in 0..attribute_count { + if let Some(att) = read_attribute(constant_pool.clone(), &info, &mut code_index) { + code_attributes.push(att); + } + } + Some(AttributeType::Code(MethodCode::new(max_stack, max_locals, code, exception_table, code_attributes))) + } + "SourceFile" => Some(AttributeType::SourceFile), + _ => None + }; } -} - -fn get_u16(data: &[u8], pos: usize) -> u16 { - u16::from_be_bytes(data[pos..pos + 2].try_into().expect("slice with incorrect length")) -} - -fn get_i32(data: &[u8], pos: usize) -> i32 { - i32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length")) -} - -fn read_u32(data: &[u8], pos: usize) -> u32 { - u32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length")) -} - -fn get_f32(data: &[u8], pos: usize) -> f32 { - f32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length")) -} - -fn get_i64(data: &[u8], pos: usize) -> i64 { - i64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length")) -} - -fn get_f64(data: &[u8], pos: usize) -> f64 { - f64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length")) + None } #[derive(Debug)] pub enum CpEntry { - Utf8(String), - Integer(i32), - Float(f32), - Long(i64), - Double(f64), - ClassRef(u16), - StringRef(u16), - Fieldref(u16, u16), - MethodRef(u16, u16), - InterfaceMethodref(u16, u16), - NameAndType(usize, usize), + Utf8(usize, String), + Integer(usize, i32), + Float(usize, f32), + Long(usize, i64), + Double(usize, f64), + ClassRef(usize, u16), + StringRef(usize, u16), + Fieldref(usize, u16, u16), + MethodRef(usize, u16, u16), + InterfaceMethodref(usize, u16, u16), + NameAndType(usize, usize, usize), } - - - - diff --git a/src/types.rs b/src/types.rs index 7c8b358..dd1999a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,6 +1,5 @@ use std::rc::Rc; use crate::CpEntry; -use crate::CpEntry::NameAndType; #[derive(Debug)] //TODO create factory function @@ -14,7 +13,7 @@ pub struct Class { pub interfaces: Vec, pub fields: Vec, pub methods: Vec, - pub attributes: Vec, + pub attributes: Vec, } impl Class { @@ -23,13 +22,19 @@ impl Class { } } -#[derive(Debug)] pub struct Method { constant_pool: Rc>, access_flags: u16, name_index: usize, descriptor_index: usize, - attributes: Vec, + attributes: Vec, +} + +impl fmt::Debug for Method { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Method {{access_flags: {}, name_index: {}, descriptor_index: {}, attributes: {:?} }}", + self.access_flags, self.name_index, self.descriptor_index, self.attributes) + } } impl Method { @@ -37,16 +42,16 @@ impl Method { access_flags: u16, name_index: usize, descriptor_index: usize, - attributes: Vec, ) -> Self { + attributes: Vec, ) -> Self { Method { constant_pool, access_flags, name_index, descriptor_index, attributes } } pub fn name(&self) -> String { let mut full_name = get_modifier(self.access_flags); - if let CpEntry::Utf8(s) = &self.constant_pool[&self.name_index - 1] { + if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.name_index - 1] { full_name.push_str(s); } - if let CpEntry::Utf8(s) = &self.constant_pool[&self.descriptor_index - 1] { + if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.descriptor_index - 1] { full_name.push_str(s); } @@ -54,25 +59,34 @@ impl Method { full_name } - pub fn get_code(&self) { - for att in &self.attributes { - if let CpEntry::Utf8(str) = &self.constant_pool[&att.attribute_name_index - 1] { - println!("{}", str); - if str == "Code" { - println!("{:?}", att.info); - } - } - } - } + // pub fn get_code(&self) { + // for att in &self.attributes { + // if let CpEntry::Utf8(_, str) = &self.constant_pool[&att.attribute_name_index - 1] { + // println!("{}", str); + // if str == "Code" { + // println!("{:?}", att.info); + // } + // } + // } + // } } -#[derive(Debug)] pub struct Field { constant_pool: Rc>, access_flags: u16, name_index: usize, descriptor_index: usize, - _attributes: Vec, + attributes: Vec, +} + +use std::fmt; +use crate::io::read_u16; + +impl fmt::Debug for Field { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Field {{access_flags: {}, name_index: {}, descriptor_index: {}, attributes: {:?} }}", + self.access_flags, self.name_index, self.descriptor_index, self.attributes) + } } impl Field { @@ -80,18 +94,18 @@ impl Field { access_flags: u16, name_index: usize, descriptor_index: usize, - attributes: Vec, ) -> Self { - Field { constant_pool, access_flags, name_index, descriptor_index, _attributes: attributes } + attributes: Vec, ) -> Self { + Field { constant_pool, access_flags, name_index, descriptor_index, attributes: attributes } } pub fn name(&self) -> String { let mut full_name = get_modifier(self.access_flags); - if let CpEntry::Utf8(s) = &self.constant_pool[&self.descriptor_index - 1] { + if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.descriptor_index - 1] { full_name.push_str(s); } full_name.push(' '); - if let CpEntry::Utf8(s) = &self.constant_pool[&self.name_index - 1] { + if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.name_index - 1] { full_name.push_str(s); } @@ -99,13 +113,6 @@ impl Field { } } -#[derive(Debug)] -pub struct Attribute { - pub attribute_name_index: usize, - pub info: Vec, -} - - const MODIFIERS: [(u16, &str); 12] = [ (0x0001, "public "), (0x0002, "private "), @@ -120,21 +127,19 @@ const MODIFIERS: [(u16, &str); 12] = [ (0x0400, "interface "), (0x0800, "strict ")]; -pub fn get_modifier(value: u16) -> String { +pub fn get_modifier(modifier: u16) -> String { let mut output = String::new(); for m in MODIFIERS { - if value & m.0 == m.0 { output.push_str(m.1) } + if modifier & m.0 == m.0 { output.push_str(m.1) } } output } -use std::cell::OnceCell; -use std::collections::HashMap; -use crate::types::AttributeType::{BootstrapMethods, Code, ConstantValue, NestHost, NestMembers, PermittedSubclasses, StackMapTable}; -enum AttributeType { - ConstantValue, - Code, +#[derive(Debug)] +pub enum AttributeType { + ConstantValue(u16), + Code(MethodCode), StackMapTable, BootstrapMethods, NestHost, @@ -165,16 +170,39 @@ enum AttributeType { ModuleMainClass, } -const cell: OnceCell> = OnceCell::new(); +#[derive(Debug)] +pub struct Exception { + pub start_pc: u16, + pub end_pc: u16, + pub handler_pc: u16, + pub catch_type: u16, +} -const value: &HashMap<&str, AttributeType> = cell.get_or_init(|| { - let mut map = HashMap::with_capacity(18); - map.insert("ConstantValue", ConstantValue); - map.insert("Code", Code); - map.insert("StackMapTable", StackMapTable); - map.insert("BootstrapMethods", BootstrapMethods); - map.insert("NestHost", NestHost); - map.insert("NestMembers", NestMembers); - map.insert("PermittedSubclasses", PermittedSubclasses); - map -}); \ No newline at end of file +impl Exception { + pub fn read(code: &[u8], index: usize) -> Self { + Self { + start_pc: read_u16(code, index), + end_pc: read_u16(code, index + 2), + handler_pc: read_u16(code, index + 4), + catch_type: read_u16(code, index + 6), + } + } +} + +#[derive(Debug)] +pub struct MethodCode { + max_stack: u16, + max_locals: u16, + code: Vec, + exception_table: Vec, + code_attributes: Vec, +} + +impl MethodCode { + pub(crate) fn new(max_stack: u16, max_locals: u16, + code: Vec, + exception_table: Vec, + code_attributes: Vec) -> Self { + Self { max_stack, max_locals, code, exception_table, code_attributes } + } +} \ No newline at end of file diff --git a/tests/class_tests.rs b/tests/class_tests.rs index 87ada89..c4935e4 100644 --- a/tests/class_tests.rs +++ b/tests/class_tests.rs @@ -1,7 +1,7 @@ mod test { use std::rc::Rc; use classfile_reader::CpEntry::*; - use classfile_reader::types::{Attribute, Class, Field, Method}; + use classfile_reader::types::{AttributeType, Class, Field, Method}; #[test] fn get_version() { @@ -25,43 +25,43 @@ mod test { #[test] fn get_code() { let class = get_class(); - println!("{:?}", &class.methods[0].get_code()); - println!("{:?}", &class.methods[1].get_code()); + // println!("{:?}", &class.methods[0].get_code()); + // println!("{:?}", &class.methods[1].get_code()); } fn get_class() -> Class { let cp = Rc::new(vec![ - MethodRef(6, 19), - Fieldref(5, 20), - Fieldref(21, 22), - MethodRef(23, 24), - ClassRef(25), - ClassRef(26), - Utf8("name".to_owned()), - Utf8("Ljava/lang/String;".to_owned()), - Utf8("".to_owned()), - Utf8("(Ljava/lang/String;)V".to_owned()), //10 - Utf8("Code".to_owned()), - Utf8("LineNumberTable".to_owned()), - Utf8("getName".to_owned()), - Utf8("()Ljava/lang/String;".to_owned()), - Utf8("print".to_owned()), - Utf8("()V".to_owned()), - Utf8("SourceFile".to_owned()), - Utf8("Dummy.java".to_owned()), - NameAndType(9, 16), - NameAndType(7, 8), //20 - ClassRef(27), - NameAndType(28, 29), - ClassRef(30), - NameAndType(31, 10), - Utf8("dummy/Dummy".to_owned()), - Utf8("java/lang/Object".to_owned()), - Utf8("java/lang/System".to_owned()), - Utf8("out".to_owned()), - Utf8("Ljava/io/PrintStream;".to_owned()), - Utf8("java/io/PrintStream".to_owned()), - Utf8("println".to_owned()), + MethodRef(1, 6, 19), + Fieldref(2, 5, 20), + Fieldref(3, 21, 22), + MethodRef(4, 23, 24), + ClassRef(5, 25), + ClassRef(6, 26), + Utf8(7, "name".to_owned()), + Utf8(8, "Ljava/lang/String;".to_owned()), + Utf8(9, "".to_owned()), + Utf8(10, "(Ljava/lang/String;)V".to_owned()), //10 + Utf8(11, "Code".to_owned()), + Utf8(12, "LineNumberTable".to_owned()), + Utf8(13, "getName".to_owned()), + Utf8(14, "()Ljava/lang/String;".to_owned()), + Utf8(15, "print".to_owned()), + Utf8(16, "()V".to_owned()), + Utf8(17, "SourceFile".to_owned()), + Utf8(18, "Dummy.java".to_owned()), + NameAndType(19, 9, 16), + NameAndType(20, 7, 8), //20 + ClassRef(21, 27), + NameAndType(22, 28, 29), + ClassRef(23, 30), + NameAndType(24, 31, 10), + Utf8(25, "dummy/Dummy".to_owned()), + Utf8(26, "java/lang/Object".to_owned()), + Utf8(27, "java/lang/System".to_owned()), + Utf8(28, "out".to_owned()), + Utf8(29, "Ljava/io/PrintStream;".to_owned()), + Utf8(30, "java/io/PrintStream".to_owned()), + Utf8(31, "println".to_owned()), ]); Class { @@ -74,27 +74,15 @@ mod test { interfaces: vec![], methods: vec![ Method::new( - cp.clone(), 1, 9, 10, vec![Attribute { - attribute_name_index: 11, - info: vec![0, 2, 0, 2, 0, 0, 0, 10, 42, 183, 0, 1, 42, 43, 181, 0, 2, 177, 0, - 0, 0, 1, 0, 12, 0, 0, 0, 14, 0, 3, 0, 0, 0, 7, 0, 4, 0, 8, 0, 9, 0, 9], - }], + cp.clone(), 1, 9, 10, vec![AttributeType::Deprecated + ], ), Method::new( - cp.clone(), 1, 13, 14, vec![Attribute { - attribute_name_index: 11, - info: vec![0, 1, 0, 1, 0, 0, 0, 5, 42, 180, 0, 2, 176, 0, 0, 0, 1, 0, 12, 0, - 0, 0, 6, 0, 1, 0, 0, 0, 12], - }], - ), - Method::new(cp.clone(), 1, 15, 16, vec![Attribute { - attribute_name_index: 11, - info: vec![0, 2, 0, 1, 0, 0, 0, 11, 178, 0, 3, 42, 180, 0, 2, 182, 0, 4, 177, 0, - 0, 0, 1, 0, 12, 0, 0, 0, 10, 0, 2, 0, 0, 0, 16, 0, 10, 0, 17], - }]), + cp.clone(), 1, 13, 14, vec![AttributeType::Deprecated]), + Method::new(cp.clone(), 1, 15, 16, vec![AttributeType::Deprecated]), ], fields: vec![Field::new(cp, 18, 7, 8, vec![])], - attributes: vec![Attribute { attribute_name_index: 17, info: vec![0, 18] }], + attributes: vec![AttributeType::SourceFile], } } } \ No newline at end of file