added constantvalue and code attribute

This commit is contained in:
Shautvast 2023-09-23 08:23:08 +02:00
parent 84a3c1e80c
commit b06a20a7b1
7 changed files with 260 additions and 199 deletions

Binary file not shown.

View file

@ -2,6 +2,9 @@ package dummy;
public class Dummy { public class Dummy {
private final static String constant = "meh";
private final int integer = 57;
private final String name; private final String name;
public Dummy(String name) { public Dummy(String name) {

23
src/io.rs Normal file
View file

@ -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"))
}

View file

@ -1,56 +1,63 @@
pub mod types; pub mod types;
mod io;
use std::rc::Rc; 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<u8>) -> Option<Class> { pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
check_magic(&bytecode); 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 index = 10;
let mut constant_pool: Vec<CpEntry> = vec![]; let mut constant_pool: Vec<CpEntry> = vec![];
for _ in 0..constant_pool_count - 1 { for cp_index in 0..constant_pool_count - 1 {
constant_pool.push(read_constant_pool_entry(&mut index, &bytecode)); constant_pool.push(read_constant_pool_entry((cp_index + 1) as usize, &mut index, &bytecode));
} }
let constant_pool = Rc::new(constant_pool); let constant_pool = Rc::new(constant_pool);
let access_flags = get_u16(&bytecode, index); let access_flags = read_u16(&bytecode, index);
let this_class = get_u16(&bytecode, index + 2); let this_class = read_u16(&bytecode, index + 2);
let super_class = get_u16(&bytecode, index + 4); 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; index += 8;
let mut interfaces = vec![]; let mut interfaces = vec![];
for _ in 0..interfaces_count { for _ in 0..interfaces_count {
interfaces.push(get_u16(&bytecode, index)); interfaces.push(read_u16(&bytecode, index));
index += 2; index += 2;
} }
let fields_count = get_u16(&bytecode, index); let fields_count = read_u16(&bytecode, index);
index += 2; index += 2;
let mut fields = vec![]; let mut fields = vec![];
for _ in 0..fields_count { for _ in 0..fields_count {
fields.push(read_field(constant_pool.clone(), &mut index, &bytecode)); 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; index += 2;
let mut methods = vec![]; let mut methods = vec![];
for _ in 0..methods_count { for _ in 0..methods_count {
methods.push(read_method(constant_pool.clone(), &mut index, &bytecode)); 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; index += 2;
let mut attributes = vec![]; let mut attributes = vec![];
for _ in 0..attributes_count { 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 { Some(Class {
minor_version: get_u16(&bytecode, 4), minor_version: read_u16(&bytecode, 4),
major_version: get_u16(&bytecode, 6), major_version: read_u16(&bytecode, 6),
constant_pool, constant_pool,
access_flags, access_flags,
this_class, 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]; let tag = bytecode[*index];
match tag { match tag {
1 => { 1 => {
let len = get_u16(bytecode, *index + 1) as usize; let len = read_u16(bytecode, *index + 1) as usize;
let utf: Vec<u8> = Vec::from(&bytecode[*index + 3..*index + 3 + len]); let utf: Vec<u8> = Vec::from(&bytecode[*index + 3..*index + 3 + len]);
*index += len + 3; *index += len + 3;
CpEntry::Utf8(String::from_utf8(utf).unwrap()) CpEntry::Utf8(cp_index, String::from_utf8(utf).unwrap())
} }
3 => { 3 => {
let value = get_i32(bytecode, *index + 1); let value = read_i32(bytecode, *index + 1);
*index += 5; *index += 5;
CpEntry::Integer(value) CpEntry::Integer(cp_index, value)
} }
4 => { 4 => {
let value = get_f32(bytecode, *index + 1); let value = read_f32(bytecode, *index + 1);
*index += 5; *index += 5;
CpEntry::Float(value) CpEntry::Float(cp_index, value)
} }
5 => { 5 => {
let value = get_i64(bytecode, *index + 1); let value = read_i64(bytecode, *index + 1);
*index += 9; *index += 9;
CpEntry::Long(value) CpEntry::Long(cp_index, value)
} }
6 => { 6 => {
let value = get_f64(bytecode, *index + 1); let value = read_f64(bytecode, *index + 1);
*index += 9; *index += 9;
CpEntry::Double(value) CpEntry::Double(cp_index, value)
} }
7 => { 7 => {
let name_index = get_u16(bytecode, *index + 1); let name_index = read_u16(bytecode, *index + 1);
*index += 3; *index += 3;
CpEntry::ClassRef(name_index) CpEntry::ClassRef(cp_index, name_index)
} }
8 => { 8 => {
let string_index = get_u16(bytecode, *index + 1); let string_index = read_u16(bytecode, *index + 1);
*index += 3; *index += 3;
CpEntry::StringRef(string_index) CpEntry::StringRef(cp_index, string_index)
} }
9 => { 9 => {
let class_index = get_u16(bytecode, *index + 1); let class_index = read_u16(bytecode, *index + 1);
let name_and_type_index = get_u16(bytecode, *index + 3); let name_and_type_index = read_u16(bytecode, *index + 3);
*index += 5; *index += 5;
CpEntry::Fieldref(class_index, name_and_type_index) CpEntry::Fieldref(cp_index, class_index, name_and_type_index)
} }
10 => { 10 => {
let class_index = get_u16(bytecode, *index + 1); let class_index = read_u16(bytecode, *index + 1);
let name_and_type_index = get_u16(bytecode, *index + 3); let name_and_type_index = read_u16(bytecode, *index + 3);
*index += 5; *index += 5;
CpEntry::MethodRef(class_index, name_and_type_index) CpEntry::MethodRef(cp_index, class_index, name_and_type_index)
} }
11 => { 11 => {
let class_index = get_u16(bytecode, *index + 1); let class_index = read_u16(bytecode, *index + 1);
let name_and_type_index = get_u16(bytecode, *index + 3); let name_and_type_index = read_u16(bytecode, *index + 3);
*index += 5; *index += 5;
CpEntry::InterfaceMethodref(class_index, name_and_type_index) CpEntry::InterfaceMethodref(cp_index, class_index, name_and_type_index)
} }
12 => { 12 => {
let name_index = get_u16(bytecode, *index + 1) as usize; let name_index = read_u16(bytecode, *index + 1) as usize;
let descriptor_index = get_u16(bytecode, *index + 3) as usize; let descriptor_index = read_u16(bytecode, *index + 3) as usize;
*index += 5; *index += 5;
CpEntry::NameAndType(name_index, descriptor_index) CpEntry::NameAndType(cp_index, name_index, descriptor_index)
} }
// 15 MethodHandle, // 15 MethodHandle,
// 16 MethodType, // 16 MethodType,
@ -142,14 +149,18 @@ fn read_constant_pool_entry(index: &mut usize, bytecode: &[u8]) -> CpEntry {
} }
fn read_field(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Field { fn read_field(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Field {
let access_flags = get_u16(bytecode, *index); let access_flags = read_u16(bytecode, *index);
let name_index = get_u16(bytecode, *index + 2) as usize; let name_index = read_u16(bytecode, *index + 2) as usize;
let descriptor_index = get_u16(bytecode, *index + 4) as usize; let descriptor_index = read_u16(bytecode, *index + 4) as usize;
let attributes_count = get_u16(bytecode, *index + 6); let attributes_count = read_u16(bytecode, *index + 6);
*index += 8; *index += 8;
let mut attributes = vec![]; let mut attributes = vec![];
for _ in 0..attributes_count { 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( Field::new(
constant_pool, constant_pool,
@ -161,15 +172,19 @@ fn read_field(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8
} }
fn read_method(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Method { fn read_method(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Method {
let access_flags = get_u16(bytecode, *index); let access_flags = read_u16(bytecode, *index);
let name_index = get_u16(bytecode, *index + 2) as usize; let name_index = read_u16(bytecode, *index + 2) as usize;
let descriptor_index = get_u16(bytecode, *index + 4) as usize; let descriptor_index = read_u16(bytecode, *index + 4) as usize;
let attributes_count = get_u16(bytecode, *index + 6); let attributes_count = read_u16(bytecode, *index + 6);
*index += 8; *index += 8;
let mut attributes = vec![]; let mut attributes = vec![];
for _ in 0..attributes_count { 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, constant_pool,
access_flags, access_flags,
@ -179,60 +194,64 @@ fn read_method(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u
) )
} }
fn read_attribute(constant_pool: Rc<Vec<CpEntry>>, bytecode: &[u8], index: &mut usize) -> Attribute { fn read_attribute(constant_pool: Rc<Vec<CpEntry>>, bytecode: &[u8], index: &mut usize) -> Option<AttributeType> {
let attribute_name_index = get_u16(bytecode, *index) as usize; let attribute_name_index = read_u16(bytecode, *index) as usize;
*index += 2; *index += 2;
let attribute_length = read_u32(bytecode, *index) as usize; let attribute_length = read_u32(bytecode, *index) as usize;
*index += 4; *index += 4;
let info: Vec<u8> = Vec::from(&bytecode[*index..*index + attribute_length]); let info: Vec<u8> = Vec::from(&bytecode[*index..*index + attribute_length]);
*index += attribute_length; *index += attribute_length;
Attribute {
attribute_name_index,
info,
}
}
fn get_u16(data: &[u8], pos: usize) -> u16 { if let CpEntry::Utf8(_, s) = &constant_pool[attribute_name_index - 1] {
u16::from_be_bytes(data[pos..pos + 2].try_into().expect("slice with incorrect length")) // 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;
fn get_i32(data: &[u8], pos: usize) -> i32 { let mut code_index = 10 + code_length;
i32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect 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);
fn read_u32(data: &[u8], pos: usize) -> u32 { code_index += 2;
u32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length")) 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);
} }
fn get_f32(data: &[u8], pos: usize) -> f32 {
f32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length"))
} }
Some(AttributeType::Code(MethodCode::new(max_stack, max_locals, code, exception_table, code_attributes)))
fn get_i64(data: &[u8], pos: usize) -> i64 {
i64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length"))
} }
"SourceFile" => Some(AttributeType::SourceFile),
fn get_f64(data: &[u8], pos: usize) -> f64 { _ => None
f64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length")) };
}
None
} }
#[derive(Debug)] #[derive(Debug)]
pub enum CpEntry { pub enum CpEntry {
Utf8(String), Utf8(usize, String),
Integer(i32), Integer(usize, i32),
Float(f32), Float(usize, f32),
Long(i64), Long(usize, i64),
Double(f64), Double(usize, f64),
ClassRef(u16), ClassRef(usize, u16),
StringRef(u16), StringRef(usize, u16),
Fieldref(u16, u16), Fieldref(usize, u16, u16),
MethodRef(u16, u16), MethodRef(usize, u16, u16),
InterfaceMethodref(u16, u16), InterfaceMethodref(usize, u16, u16),
NameAndType(usize, usize), NameAndType(usize, usize, usize),
} }

View file

@ -1,6 +1,5 @@
use std::rc::Rc; use std::rc::Rc;
use crate::CpEntry; use crate::CpEntry;
use crate::CpEntry::NameAndType;
#[derive(Debug)] #[derive(Debug)]
//TODO create factory function //TODO create factory function
@ -14,7 +13,7 @@ pub struct Class {
pub interfaces: Vec<u16>, pub interfaces: Vec<u16>,
pub fields: Vec<Field>, pub fields: Vec<Field>,
pub methods: Vec<Method>, pub methods: Vec<Method>,
pub attributes: Vec<Attribute>, pub attributes: Vec<AttributeType>,
} }
impl Class { impl Class {
@ -23,13 +22,19 @@ impl Class {
} }
} }
#[derive(Debug)]
pub struct Method { pub struct Method {
constant_pool: Rc<Vec<CpEntry>>, constant_pool: Rc<Vec<CpEntry>>,
access_flags: u16, access_flags: u16,
name_index: usize, name_index: usize,
descriptor_index: usize, descriptor_index: usize,
attributes: Vec<Attribute>, attributes: Vec<AttributeType>,
}
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 { impl Method {
@ -37,16 +42,16 @@ impl Method {
access_flags: u16, access_flags: u16,
name_index: usize, name_index: usize,
descriptor_index: usize, descriptor_index: usize,
attributes: Vec<Attribute>, ) -> Self { attributes: Vec<AttributeType>, ) -> Self {
Method { constant_pool, access_flags, name_index, descriptor_index, attributes } Method { constant_pool, access_flags, name_index, descriptor_index, attributes }
} }
pub fn name(&self) -> String { pub fn name(&self) -> String {
let mut full_name = get_modifier(self.access_flags); 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); 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); full_name.push_str(s);
} }
@ -54,25 +59,34 @@ impl Method {
full_name full_name
} }
pub fn get_code(&self) { // pub fn get_code(&self) {
for att in &self.attributes { // for att in &self.attributes {
if let CpEntry::Utf8(str) = &self.constant_pool[&att.attribute_name_index - 1] { // if let CpEntry::Utf8(_, str) = &self.constant_pool[&att.attribute_name_index - 1] {
println!("{}", str); // println!("{}", str);
if str == "Code" { // if str == "Code" {
println!("{:?}", att.info); // println!("{:?}", att.info);
} // }
} // }
} // }
} // }
} }
#[derive(Debug)]
pub struct Field { pub struct Field {
constant_pool: Rc<Vec<CpEntry>>, constant_pool: Rc<Vec<CpEntry>>,
access_flags: u16, access_flags: u16,
name_index: usize, name_index: usize,
descriptor_index: usize, descriptor_index: usize,
_attributes: Vec<Attribute>, attributes: Vec<AttributeType>,
}
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 { impl Field {
@ -80,18 +94,18 @@ impl Field {
access_flags: u16, access_flags: u16,
name_index: usize, name_index: usize,
descriptor_index: usize, descriptor_index: usize,
attributes: Vec<Attribute>, ) -> Self { attributes: Vec<AttributeType>, ) -> Self {
Field { constant_pool, access_flags, name_index, descriptor_index, _attributes: attributes } Field { constant_pool, access_flags, name_index, descriptor_index, attributes: attributes }
} }
pub fn name(&self) -> String { pub fn name(&self) -> String {
let mut full_name = get_modifier(self.access_flags); 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_str(s);
} }
full_name.push(' '); 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); full_name.push_str(s);
} }
@ -99,13 +113,6 @@ impl Field {
} }
} }
#[derive(Debug)]
pub struct Attribute {
pub attribute_name_index: usize,
pub info: Vec<u8>,
}
const MODIFIERS: [(u16, &str); 12] = [ const MODIFIERS: [(u16, &str); 12] = [
(0x0001, "public "), (0x0001, "public "),
(0x0002, "private "), (0x0002, "private "),
@ -120,21 +127,19 @@ const MODIFIERS: [(u16, &str); 12] = [
(0x0400, "interface "), (0x0400, "interface "),
(0x0800, "strict ")]; (0x0800, "strict ")];
pub fn get_modifier(value: u16) -> String { pub fn get_modifier(modifier: u16) -> String {
let mut output = String::new(); let mut output = String::new();
for m in MODIFIERS { 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 output
} }
use std::cell::OnceCell;
use std::collections::HashMap;
use crate::types::AttributeType::{BootstrapMethods, Code, ConstantValue, NestHost, NestMembers, PermittedSubclasses, StackMapTable};
enum AttributeType { #[derive(Debug)]
ConstantValue, pub enum AttributeType {
Code, ConstantValue(u16),
Code(MethodCode),
StackMapTable, StackMapTable,
BootstrapMethods, BootstrapMethods,
NestHost, NestHost,
@ -165,16 +170,39 @@ enum AttributeType {
ModuleMainClass, ModuleMainClass,
} }
const cell: OnceCell<HashMap<&str, AttributeType>> = 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(|| { impl Exception {
let mut map = HashMap::with_capacity(18); pub fn read(code: &[u8], index: usize) -> Self {
map.insert("ConstantValue", ConstantValue); Self {
map.insert("Code", Code); start_pc: read_u16(code, index),
map.insert("StackMapTable", StackMapTable); end_pc: read_u16(code, index + 2),
map.insert("BootstrapMethods", BootstrapMethods); handler_pc: read_u16(code, index + 4),
map.insert("NestHost", NestHost); catch_type: read_u16(code, index + 6),
map.insert("NestMembers", NestMembers); }
map.insert("PermittedSubclasses", PermittedSubclasses); }
map }
});
#[derive(Debug)]
pub struct MethodCode {
max_stack: u16,
max_locals: u16,
code: Vec<u8>,
exception_table: Vec<Exception>,
code_attributes: Vec<AttributeType>,
}
impl MethodCode {
pub(crate) fn new(max_stack: u16, max_locals: u16,
code: Vec<u8>,
exception_table: Vec<Exception>,
code_attributes: Vec<AttributeType>) -> Self {
Self { max_stack, max_locals, code, exception_table, code_attributes }
}
}

View file

@ -1,7 +1,7 @@
mod test { mod test {
use std::rc::Rc; use std::rc::Rc;
use classfile_reader::CpEntry::*; use classfile_reader::CpEntry::*;
use classfile_reader::types::{Attribute, Class, Field, Method}; use classfile_reader::types::{AttributeType, Class, Field, Method};
#[test] #[test]
fn get_version() { fn get_version() {
@ -25,43 +25,43 @@ mod test {
#[test] #[test]
fn get_code() { fn get_code() {
let class = get_class(); let class = get_class();
println!("{:?}", &class.methods[0].get_code()); // println!("{:?}", &class.methods[0].get_code());
println!("{:?}", &class.methods[1].get_code()); // println!("{:?}", &class.methods[1].get_code());
} }
fn get_class() -> Class { fn get_class() -> Class {
let cp = Rc::new(vec![ let cp = Rc::new(vec![
MethodRef(6, 19), MethodRef(1, 6, 19),
Fieldref(5, 20), Fieldref(2, 5, 20),
Fieldref(21, 22), Fieldref(3, 21, 22),
MethodRef(23, 24), MethodRef(4, 23, 24),
ClassRef(25), ClassRef(5, 25),
ClassRef(26), ClassRef(6, 26),
Utf8("name".to_owned()), Utf8(7, "name".to_owned()),
Utf8("Ljava/lang/String;".to_owned()), Utf8(8, "Ljava/lang/String;".to_owned()),
Utf8("<init>".to_owned()), Utf8(9, "<init>".to_owned()),
Utf8("(Ljava/lang/String;)V".to_owned()), //10 Utf8(10, "(Ljava/lang/String;)V".to_owned()), //10
Utf8("Code".to_owned()), Utf8(11, "Code".to_owned()),
Utf8("LineNumberTable".to_owned()), Utf8(12, "LineNumberTable".to_owned()),
Utf8("getName".to_owned()), Utf8(13, "getName".to_owned()),
Utf8("()Ljava/lang/String;".to_owned()), Utf8(14, "()Ljava/lang/String;".to_owned()),
Utf8("print".to_owned()), Utf8(15, "print".to_owned()),
Utf8("()V".to_owned()), Utf8(16, "()V".to_owned()),
Utf8("SourceFile".to_owned()), Utf8(17, "SourceFile".to_owned()),
Utf8("Dummy.java".to_owned()), Utf8(18, "Dummy.java".to_owned()),
NameAndType(9, 16), NameAndType(19, 9, 16),
NameAndType(7, 8), //20 NameAndType(20, 7, 8), //20
ClassRef(27), ClassRef(21, 27),
NameAndType(28, 29), NameAndType(22, 28, 29),
ClassRef(30), ClassRef(23, 30),
NameAndType(31, 10), NameAndType(24, 31, 10),
Utf8("dummy/Dummy".to_owned()), Utf8(25, "dummy/Dummy".to_owned()),
Utf8("java/lang/Object".to_owned()), Utf8(26, "java/lang/Object".to_owned()),
Utf8("java/lang/System".to_owned()), Utf8(27, "java/lang/System".to_owned()),
Utf8("out".to_owned()), Utf8(28, "out".to_owned()),
Utf8("Ljava/io/PrintStream;".to_owned()), Utf8(29, "Ljava/io/PrintStream;".to_owned()),
Utf8("java/io/PrintStream".to_owned()), Utf8(30, "java/io/PrintStream".to_owned()),
Utf8("println".to_owned()), Utf8(31, "println".to_owned()),
]); ]);
Class { Class {
@ -74,27 +74,15 @@ mod test {
interfaces: vec![], interfaces: vec![],
methods: vec![ methods: vec![
Method::new( Method::new(
cp.clone(), 1, 9, 10, vec![Attribute { cp.clone(), 1, 9, 10, vec![AttributeType::Deprecated
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],
}],
), ),
Method::new( Method::new(
cp.clone(), 1, 13, 14, vec![Attribute { cp.clone(), 1, 13, 14, vec![AttributeType::Deprecated]),
attribute_name_index: 11, Method::new(cp.clone(), 1, 15, 16, vec![AttributeType::Deprecated]),
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],
}]),
], ],
fields: vec![Field::new(cp, 18, 7, 8, vec![])], fields: vec![Field::new(cp, 18, 7, 8, vec![])],
attributes: vec![Attribute { attribute_name_index: 17, info: vec![0, 18] }], attributes: vec![AttributeType::SourceFile],
} }
} }
} }