mirror of
https://github.com/Noratrieb/coldsquare.git
synced 2026-01-14 16:35:10 +01:00
Refactored CpInfo to be more nested
So I can only refer to a single variant
This commit is contained in:
parent
3546a5b268
commit
860346a910
5 changed files with 418 additions and 231 deletions
|
|
@ -2,7 +2,15 @@ use crate::parse::{ClassFile, ParseErr};
|
||||||
|
|
||||||
mod execute;
|
mod execute;
|
||||||
mod parse;
|
mod parse;
|
||||||
|
mod ui;
|
||||||
|
|
||||||
pub fn parse_class_file(file: &[u8]) -> Result<ClassFile, ParseErr> {
|
pub fn parse_class_file(file: &[u8]) -> Result<ClassFile, ParseErr> {
|
||||||
parse::parse_class_file(file)
|
parse::parse_class_file(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn display_class<W>(w: W, class: &ClassFile) -> std::io::Result<()>
|
||||||
|
where
|
||||||
|
W: std::io::Write,
|
||||||
|
{
|
||||||
|
ui::display_class(w, class)
|
||||||
|
}
|
||||||
|
|
|
||||||
25
src/main.rs
25
src/main.rs
|
|
@ -1,10 +1,25 @@
|
||||||
use coldsquare::parse_class_file;
|
use coldsquare::{display_class, parse_class_file};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let file = "Test.class";
|
let file = std::env::args().nth(1).unwrap_or_else(|| {
|
||||||
let file = std::fs::read(file).unwrap();
|
eprintln!("No file provided");
|
||||||
|
std::process::exit(1);
|
||||||
|
});
|
||||||
|
let file = std::fs::read(file).unwrap_or_else(|_| {
|
||||||
|
eprintln!("Could not read file");
|
||||||
|
std::process::exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
let class_file = parse_class_file(&file).unwrap();
|
let class_file = match parse_class_file(&file) {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
|
||||||
println!("{:?}", class_file);
|
if let Err(why) = display_class(stdout.lock(), &class_file) {
|
||||||
|
eprintln!("{}", why);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
250
src/parse/mod.rs
250
src/parse/mod.rs
|
|
@ -3,10 +3,19 @@ mod model;
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
pub use model::*;
|
pub use model::*;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParseErr(String);
|
pub struct ParseErr(String);
|
||||||
|
|
||||||
|
impl Display for ParseErr {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Could not parse class file: {}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for ParseErr {}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, ParseErr>;
|
pub type Result<T> = std::result::Result<T, ParseErr>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -35,6 +44,10 @@ impl<'a> Data<'a> {
|
||||||
Ok(((self.u1()? as u2) << 8) | self.u1()? as u2)
|
Ok(((self.u1()? as u2) << 8) | self.u1()? as u2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cp(&mut self) -> Result<FromPool> {
|
||||||
|
Ok(self.u2()?.into())
|
||||||
|
}
|
||||||
|
|
||||||
fn u4(&mut self) -> Result<u4> {
|
fn u4(&mut self) -> Result<u4> {
|
||||||
Ok(((self.u2()? as u4) << 16) | self.u2()? as u4)
|
Ok(((self.u2()? as u4) << 16) | self.u2()? as u4)
|
||||||
}
|
}
|
||||||
|
|
@ -100,6 +113,12 @@ macro_rules! parse_primitive {
|
||||||
|
|
||||||
parse_primitive!(u1, u2, u4);
|
parse_primitive!(u1, u2, u4);
|
||||||
|
|
||||||
|
impl Parse for FromPool {
|
||||||
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
|
Ok(data.u2()?.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Parse for ClassFile {
|
impl Parse for ClassFile {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
let magic = data.u4()?;
|
let magic = data.u4()?;
|
||||||
|
|
@ -109,8 +128,8 @@ impl Parse for ClassFile {
|
||||||
let constant_pool_count = data.u2()?;
|
let constant_pool_count = data.u2()?;
|
||||||
let constant_pool = parse_vec(data, constant_pool_count - 1)?; // the minus one is important
|
let constant_pool = parse_vec(data, constant_pool_count - 1)?; // the minus one is important
|
||||||
let access_flags = data.u2()?;
|
let access_flags = data.u2()?;
|
||||||
let this_class = data.u2()?;
|
let this_class = data.cp()?;
|
||||||
let super_class = data.u2()?;
|
let super_class = data.cp()?;
|
||||||
let interfaces_count = data.u2()?;
|
let interfaces_count = data.u2()?;
|
||||||
let interfaces = parse_vec(data, interfaces_count)?;
|
let interfaces = parse_vec(data, interfaces_count)?;
|
||||||
let fields_count = data.u2()?;
|
let fields_count = data.u2()?;
|
||||||
|
|
@ -148,71 +167,96 @@ impl Parse for CpInfo {
|
||||||
let tag = data.u1()?;
|
let tag = data.u1()?;
|
||||||
|
|
||||||
Ok(match tag {
|
Ok(match tag {
|
||||||
7 => Self::Class {
|
7 => Self {
|
||||||
tag,
|
tag,
|
||||||
name_index: data.u2()?,
|
inner: CpInfoInner::Class(cp_info::Class {
|
||||||
|
name_index: data.cp()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
9 => Self::Fieldref {
|
9 => Self {
|
||||||
tag,
|
tag,
|
||||||
class_index: data.u2()?,
|
inner: CpInfoInner::Fieldref(cp_info::Fieldref {
|
||||||
name_and_type_index: data.u2()?,
|
class_index: data.cp()?,
|
||||||
|
name_and_type_index: data.cp()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
10 => Self::MethodRef {
|
10 => Self {
|
||||||
tag,
|
tag,
|
||||||
class_index: data.u2()?,
|
inner: CpInfoInner::MethodRef(cp_info::MethodRef {
|
||||||
name_and_type_index: data.u2()?,
|
class_index: data.cp()?,
|
||||||
|
name_and_type_index: data.cp()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
11 => Self::InterfaceMethodref {
|
11 => Self {
|
||||||
tag,
|
tag,
|
||||||
class_index: data.u2()?,
|
inner: CpInfoInner::InterfaceMethodref(cp_info::InterfaceMethodref {
|
||||||
name_and_type_index: data.u2()?,
|
class_index: data.cp()?,
|
||||||
|
name_and_type_index: data.cp()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
8 => Self::String {
|
8 => Self {
|
||||||
tag,
|
tag,
|
||||||
string_index: data.u2()?,
|
inner: CpInfoInner::String(cp_info::String {
|
||||||
|
string_index: data.cp()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
3 => Self::Integer {
|
3 => Self {
|
||||||
tag,
|
tag,
|
||||||
bytes: data.u4()?,
|
inner: CpInfoInner::Integer(cp_info::Integer { bytes: data.u4()? }),
|
||||||
},
|
},
|
||||||
4 => Self::Float {
|
4 => Self {
|
||||||
tag,
|
tag,
|
||||||
bytes: data.u4()?,
|
inner: CpInfoInner::Float(cp_info::Float { bytes: data.u4()? }),
|
||||||
},
|
},
|
||||||
5 => Self::Long {
|
5 => Self {
|
||||||
tag,
|
tag,
|
||||||
high_bytes: data.u4()?,
|
inner: CpInfoInner::Long(cp_info::Long {
|
||||||
low_bytes: data.u4()?,
|
high_bytes: data.u4()?,
|
||||||
|
low_bytes: data.u4()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
6 => Self::Double {
|
6 => Self {
|
||||||
tag,
|
tag,
|
||||||
high_bytes: data.u4()?,
|
inner: CpInfoInner::Double(cp_info::Double {
|
||||||
low_bytes: data.u4()?,
|
high_bytes: data.u4()?,
|
||||||
|
low_bytes: data.u4()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
12 => Self::NameAndType {
|
12 => Self {
|
||||||
tag,
|
tag,
|
||||||
name_index: data.u2()?,
|
inner: CpInfoInner::NameAndType(cp_info::NameAndType {
|
||||||
descriptor_index: data.u2()?,
|
name_index: data.cp()?,
|
||||||
|
descriptor_index: data.cp()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
1 => Self::Utf8 {
|
1 => Self {
|
||||||
tag,
|
tag,
|
||||||
length: data.u2()?,
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: String::from_utf8(parse_vec(data, data.last_u2()?)?)
|
length: data.u2()?,
|
||||||
.map_err(|err| ParseErr(format!("Invalid utf8 in CpInfo::Utf8: {}", err)))?,
|
bytes: String::from_utf8(parse_vec(data, data.last_u2()?)?).map_err(|err| {
|
||||||
|
ParseErr(format!("Invalid utf8 in CpInfo::Utf8: {}", err))
|
||||||
|
})?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
15 => Self::MethodHandle {
|
15 => Self {
|
||||||
tag,
|
tag,
|
||||||
reference_kind: data.u1()?,
|
inner: CpInfoInner::MethodHandle(cp_info::MethodHandle {
|
||||||
reference_index: data.u2()?,
|
reference_kind: data.u1()?,
|
||||||
|
reference_index: data.cp()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
16 => Self::MethodType {
|
16 => Self {
|
||||||
tag,
|
tag,
|
||||||
descriptor_index: data.u2()?,
|
inner: CpInfoInner::MethodType(cp_info::MethodType {
|
||||||
|
descriptor_index: data.cp()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
18 => Self::InvokeDynamic {
|
18 => Self {
|
||||||
tag,
|
tag,
|
||||||
bootstrap_method_attr_index: data.u2()?,
|
inner: CpInfoInner::InvokeDynamic(cp_info::InvokeDynamic {
|
||||||
name_and_type_index: data.u2()?,
|
bootstrap_method_attr_index: data.u2()?,
|
||||||
|
name_and_type_index: data.cp()?,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
_ => Err(ParseErr(format!("Invalid CPInfo tag: {}", tag)))?,
|
_ => Err(ParseErr(format!("Invalid CPInfo tag: {}", tag)))?,
|
||||||
})
|
})
|
||||||
|
|
@ -223,8 +267,8 @@ impl Parse for FieldInfo {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
access_flags: data.u2()?,
|
access_flags: data.u2()?,
|
||||||
name_index: data.u2()?,
|
name_index: data.cp()?,
|
||||||
descriptor_index: data.u2()?,
|
descriptor_index: data.cp()?,
|
||||||
attributes_count: data.u2()?,
|
attributes_count: data.u2()?,
|
||||||
attributes: parse_vec(data, data.last_u2()?)?,
|
attributes: parse_vec(data, data.last_u2()?)?,
|
||||||
})
|
})
|
||||||
|
|
@ -235,8 +279,8 @@ impl Parse for MethodInfo {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
access_flags: data.u2()?,
|
access_flags: data.u2()?,
|
||||||
name_index: data.u2()?,
|
name_index: data.cp()?,
|
||||||
descriptor_index: data.u2()?,
|
descriptor_index: data.cp()?,
|
||||||
attributes_count: data.u2()?,
|
attributes_count: data.u2()?,
|
||||||
attributes: parse_vec(data, data.last_u2()?)?,
|
attributes: parse_vec(data, data.last_u2()?)?,
|
||||||
})
|
})
|
||||||
|
|
@ -246,7 +290,7 @@ impl Parse for MethodInfo {
|
||||||
impl Parse for AttributeInfo {
|
impl Parse for AttributeInfo {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
attribute_name_index: data.u2()?,
|
attribute_name_index: data.cp()?,
|
||||||
attribute_length: data.u4()?,
|
attribute_length: data.u4()?,
|
||||||
inner: AttributeInfoInner::Unknown {
|
inner: AttributeInfoInner::Unknown {
|
||||||
attribute_content: parse_vec(data, data.last_u4()? as usize)?,
|
attribute_content: parse_vec(data, data.last_u4()? as usize)?,
|
||||||
|
|
@ -340,9 +384,9 @@ impl Parse for VerificationTypeInfo {
|
||||||
impl Parse for AttributeInnerClass {
|
impl Parse for AttributeInnerClass {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner_class_info_index: data.u2()?,
|
inner_class_info_index: data.cp()?,
|
||||||
outer_class_info_index: data.u2()?,
|
outer_class_info_index: data.cp()?,
|
||||||
inner_class_name_index: data.u2()?,
|
inner_class_name_index: data.cp()?,
|
||||||
inner_class_access_flags: data.u2()?,
|
inner_class_access_flags: data.u2()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -362,8 +406,8 @@ impl Parse for AttributeLocalVariableTable {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
start_pc: data.u2()?,
|
start_pc: data.u2()?,
|
||||||
length: data.u2()?,
|
length: data.u2()?,
|
||||||
name_index: data.u2()?,
|
name_index: data.cp()?,
|
||||||
descriptor_or_signature_index: data.u2()?,
|
descriptor_or_signature_index: data.cp()?,
|
||||||
index: data.u2()?,
|
index: data.u2()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -372,7 +416,7 @@ impl Parse for AttributeLocalVariableTable {
|
||||||
impl Parse for Annotation {
|
impl Parse for Annotation {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
type_index: data.u2()?,
|
type_index: data.cp()?,
|
||||||
num_element_value_pairs: data.u2()?,
|
num_element_value_pairs: data.u2()?,
|
||||||
element_value_pairs: parse_vec(data, data.last_u2()?)?,
|
element_value_pairs: parse_vec(data, data.last_u2()?)?,
|
||||||
})
|
})
|
||||||
|
|
@ -382,7 +426,7 @@ impl Parse for Annotation {
|
||||||
impl Parse for AnnotationElementValuePair {
|
impl Parse for AnnotationElementValuePair {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
element_name_index: data.u2()?,
|
element_name_index: data.cp()?,
|
||||||
element_name_name: AnnotationElementValue::parse(data)?,
|
element_name_name: AnnotationElementValue::parse(data)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -402,13 +446,13 @@ impl Parse for AnnotationElementValueValue {
|
||||||
let tag = data.last_u1()? as char;
|
let tag = data.last_u1()? as char;
|
||||||
Ok(match tag {
|
Ok(match tag {
|
||||||
'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's' => {
|
'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's' => {
|
||||||
Self::ConstValueIndex { index: data.u2()? }
|
Self::ConstValueIndex { index: data.cp()? }
|
||||||
}
|
}
|
||||||
'e' => Self::EnumConstValue {
|
'e' => Self::EnumConstValue {
|
||||||
type_name_index: data.u2()?,
|
type_name_index: data.cp()?,
|
||||||
const_name_index: data.u2()?,
|
const_name_index: data.cp()?,
|
||||||
},
|
},
|
||||||
'c' => Self::ClassInfoIndex { index: data.u2()? },
|
'c' => Self::ClassInfoIndex { index: data.cp()? },
|
||||||
'@' => Self::AnnotationValue {
|
'@' => Self::AnnotationValue {
|
||||||
annotation: Box::new(Annotation::parse(data)?),
|
annotation: Box::new(Annotation::parse(data)?),
|
||||||
},
|
},
|
||||||
|
|
@ -436,7 +480,7 @@ impl Parse for ParameterAnnotation {
|
||||||
impl Parse for BootstrapMethod {
|
impl Parse for BootstrapMethod {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
bootstrap_method_ref: data.u2()?,
|
bootstrap_method_ref: data.cp()?,
|
||||||
num_bootstrap_arguments: data.u2()?,
|
num_bootstrap_arguments: data.u2()?,
|
||||||
bootstrap_arguments: parse_vec(data, data.last_u2()?)?,
|
bootstrap_arguments: parse_vec(data, data.last_u2()?)?,
|
||||||
})
|
})
|
||||||
|
|
@ -449,9 +493,33 @@ fn resolve_attributes(class: &mut ClassFile) -> Result<()> {
|
||||||
class
|
class
|
||||||
.attributes
|
.attributes
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|attr| AttributeInfo::resolve_attribute(attr, pool))
|
.map(|attr| attr.resolve_attribute(pool))
|
||||||
.collect::<Result<Vec<()>>>()?;
|
.collect::<Result<Vec<()>>>()?;
|
||||||
|
|
||||||
|
class
|
||||||
|
.methods
|
||||||
|
.iter_mut()
|
||||||
|
.map(|method| {
|
||||||
|
method
|
||||||
|
.attributes
|
||||||
|
.iter_mut()
|
||||||
|
.map(|attr| attr.resolve_attribute(pool))
|
||||||
|
.collect::<Result<Vec<()>>>()
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
|
class
|
||||||
|
.fields
|
||||||
|
.iter_mut()
|
||||||
|
.map(|method| {
|
||||||
|
method
|
||||||
|
.attributes
|
||||||
|
.iter_mut()
|
||||||
|
.map(|attr| attr.resolve_attribute(pool))
|
||||||
|
.collect::<Result<Vec<()>>>()
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -461,7 +529,7 @@ impl AttributeInfo {
|
||||||
let attr = std::mem::replace(
|
let attr = std::mem::replace(
|
||||||
self,
|
self,
|
||||||
AttributeInfo {
|
AttributeInfo {
|
||||||
attribute_name_index: 0,
|
attribute_name_index: 0.into(),
|
||||||
attribute_length: 0,
|
attribute_length: 0,
|
||||||
inner: AttributeInfoInner::__Empty,
|
inner: AttributeInfoInner::__Empty,
|
||||||
},
|
},
|
||||||
|
|
@ -475,22 +543,26 @@ impl AttributeInfo {
|
||||||
} => (attribute_name_index, attribute_length, attribute_content),
|
} => (attribute_name_index, attribute_length, attribute_content),
|
||||||
_ => unreachable!("Attribute already resolved"),
|
_ => unreachable!("Attribute already resolved"),
|
||||||
};
|
};
|
||||||
let info = match pool.get(index as usize - 1) {
|
let info = match pool.get((*index) as usize - 1) {
|
||||||
Some(CpInfo::Utf8 { bytes, .. }) => bytes,
|
Some(CpInfo {
|
||||||
|
inner: CpInfoInner::Utf8(cp_info::Utf8 { bytes, .. }),
|
||||||
|
..
|
||||||
|
}) => bytes,
|
||||||
Some(_) => return Err(ParseErr("Attribute name is not CpInfo::Utf8".to_string())),
|
Some(_) => return Err(ParseErr("Attribute name is not CpInfo::Utf8".to_string())),
|
||||||
_ => return Err(ParseErr("Constant Pool index out of Bounds".to_string())),
|
_ => return Err(ParseErr("Constant Pool index out of Bounds".to_string())),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut data = Data::new(&content);
|
let mut data = Data::new(&content);
|
||||||
self.resolve_attribute_inner(index, len, info, &mut data)
|
self.resolve_attribute_inner(index, len, info, &mut data, pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_attribute_inner(
|
fn resolve_attribute_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
attribute_name_index: u16,
|
attribute_name_index: FromPool,
|
||||||
attribute_length: u32,
|
attribute_length: u32,
|
||||||
name: &str,
|
name: &str,
|
||||||
data: &mut Data,
|
data: &mut Data,
|
||||||
|
pool: &[CpInfo],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let _ = std::mem::replace(
|
let _ = std::mem::replace(
|
||||||
self,
|
self,
|
||||||
|
|
@ -499,23 +571,37 @@ impl AttributeInfo {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::ConstantValue {
|
inner: AttributeInfoInner::ConstantValue {
|
||||||
constantvalue_index: data.u2()?,
|
constantvalue_index: data.cp()?,
|
||||||
},
|
|
||||||
},
|
|
||||||
"Code" => Self {
|
|
||||||
attribute_name_index,
|
|
||||||
attribute_length,
|
|
||||||
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()?)?,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"Code" => {
|
||||||
|
let mut code = Self {
|
||||||
|
attribute_name_index,
|
||||||
|
attribute_length,
|
||||||
|
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()?)?,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if let AttributeInfoInner::Code {
|
||||||
|
ref mut attributes, ..
|
||||||
|
} = code.inner
|
||||||
|
{
|
||||||
|
attributes
|
||||||
|
.iter_mut()
|
||||||
|
.map(|attr| attr.resolve_attribute(pool))
|
||||||
|
.collect::<Result<Vec<()>>>()?;
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
code
|
||||||
|
}
|
||||||
"StackMapTable" => Self {
|
"StackMapTable" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
|
|
@ -544,8 +630,8 @@ impl AttributeInfo {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::EnclosingMethod {
|
inner: AttributeInfoInner::EnclosingMethod {
|
||||||
class_index: data.u2()?,
|
class_index: data.cp()?,
|
||||||
method_index: data.u2()?,
|
method_index: data.cp()?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Synthetic" => Self {
|
"Synthetic" => Self {
|
||||||
|
|
@ -557,14 +643,14 @@ impl AttributeInfo {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::Signature {
|
inner: AttributeInfoInner::Signature {
|
||||||
signature_index: data.u2()?,
|
signature_index: data.cp()?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"SourceFile" => Self {
|
"SourceFile" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::SourceFile {
|
inner: AttributeInfoInner::SourceFile {
|
||||||
sourcefile_index: data.u2()?,
|
sourcefile_index: data.cp()?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"SourceDebugExtension" => Self {
|
"SourceDebugExtension" => Self {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,32 @@ pub type u2 = u16;
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type u4 = u32;
|
pub type u4 = u32;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// An index into the constant pool of the class
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
|
pub struct FromPool(u2);
|
||||||
|
|
||||||
|
impl std::ops::Deref for FromPool {
|
||||||
|
type Target = u2;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u2> for FromPool {
|
||||||
|
fn from(n: u2) -> Self {
|
||||||
|
Self(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromPool {
|
||||||
|
pub fn get<'a>(&self, pool: &'a [CpInfo]) -> &'a CpInfo {
|
||||||
|
&pool[self.0 as usize - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// # Represents a .class file
|
/// # Represents a .class file
|
||||||
///
|
///
|
||||||
|
|
@ -30,9 +56,9 @@ pub struct ClassFile {
|
||||||
/// Mask of `ClassAccessFlag` used to denote access permissions
|
/// Mask of `ClassAccessFlag` used to denote access permissions
|
||||||
pub access_flags: u2,
|
pub access_flags: u2,
|
||||||
/// A valid index into the `constant_pool` table. The entry must be a `ConstantClassInfo`
|
/// A valid index into the `constant_pool` table. The entry must be a `ConstantClassInfo`
|
||||||
pub this_class: u2,
|
pub this_class: FromPool,
|
||||||
/// Zero or a valid index into the `constant_pool` table
|
/// Zero or a valid index into the `constant_pool` table
|
||||||
pub super_class: u2,
|
pub super_class: FromPool,
|
||||||
/// The number if direct superinterfaces of this class or interface type
|
/// The number if direct superinterfaces of this class or interface type
|
||||||
pub 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`
|
/// Each entry must be a valid index into the `constant_pool` table. The entry must be a `ConstantClassInfo`
|
||||||
|
|
@ -55,107 +81,135 @@ pub struct ClassFile {
|
||||||
/// May have indices back to the constant pool, with expected types
|
/// May have indices back to the constant pool, with expected types
|
||||||
/// _index: A valid index into the `constant_pool` table.
|
/// _index: A valid index into the `constant_pool` table.
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub enum CpInfo {
|
pub struct CpInfo {
|
||||||
Class {
|
pub tag: u1,
|
||||||
tag: u1, // 7
|
pub inner: CpInfoInner,
|
||||||
/// Entry must be `Utf8`
|
}
|
||||||
name_index: u2,
|
|
||||||
},
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
Fieldref {
|
pub enum CpInfoInner {
|
||||||
tag: u1, // 9
|
Class(cp_info::Class),
|
||||||
/// May be a class or interface type
|
Fieldref(cp_info::Fieldref),
|
||||||
class_index: u2,
|
MethodRef(cp_info::MethodRef),
|
||||||
/// Entry must be `NameAndType`
|
InterfaceMethodref(cp_info::InterfaceMethodref),
|
||||||
name_and_type_index: u2,
|
String(cp_info::String),
|
||||||
},
|
Integer(cp_info::Integer),
|
||||||
MethodRef {
|
Float(cp_info::Float),
|
||||||
tag: u1, // 10
|
|
||||||
/// Must be a class type
|
|
||||||
class_index: u2,
|
|
||||||
/// Entry must be `NameAndType`
|
|
||||||
name_and_type_index: u2,
|
|
||||||
},
|
|
||||||
InterfaceMethodref {
|
|
||||||
tag: u1, // 11
|
|
||||||
/// Must be an interface type
|
|
||||||
class_index: u2,
|
|
||||||
/// Entry must be `NameAndType`
|
|
||||||
name_and_type_index: u2,
|
|
||||||
},
|
|
||||||
String {
|
|
||||||
tag: u1, // 8
|
|
||||||
/// Entry must be `Utf8`
|
|
||||||
string_index: u2,
|
|
||||||
},
|
|
||||||
Integer {
|
|
||||||
tag: u1, // 3
|
|
||||||
// Big endian
|
|
||||||
bytes: u4,
|
|
||||||
},
|
|
||||||
Float {
|
|
||||||
tag: u1, // 4
|
|
||||||
/// IEEE 754 floating-point single format, big endian
|
|
||||||
bytes: u4,
|
|
||||||
},
|
|
||||||
/// 8 byte constants take up two spaces in the constant pool
|
/// 8 byte constants take up two spaces in the constant pool
|
||||||
Long {
|
Long(cp_info::Long),
|
||||||
tag: u1, // 5
|
|
||||||
/// Big endian
|
|
||||||
high_bytes: u4,
|
|
||||||
/// Big endian
|
|
||||||
low_bytes: u4,
|
|
||||||
},
|
|
||||||
/// 8 byte constants take up two spaces in the constant pool
|
/// 8 byte constants take up two spaces in the constant pool
|
||||||
Double {
|
Double(cp_info::Double),
|
||||||
tag: u1, // 6
|
|
||||||
/// IEEE 754 floating-point double format, big endian
|
|
||||||
high_bytes: u4,
|
|
||||||
/// IEEE 754 floating-point double format, big endian
|
|
||||||
low_bytes: u4,
|
|
||||||
},
|
|
||||||
/// Any field or method, without the class it belongs to
|
/// Any field or method, without the class it belongs to
|
||||||
NameAndType {
|
NameAndType(cp_info::NameAndType),
|
||||||
tag: u1, // 12
|
Utf8(cp_info::Utf8),
|
||||||
|
MethodHandle(cp_info::MethodHandle),
|
||||||
|
MethodType(cp_info::MethodType),
|
||||||
|
InvokeDynamic(cp_info::InvokeDynamic),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod cp_info {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct Class {
|
||||||
/// Entry must be `Utf8`
|
/// Entry must be `Utf8`
|
||||||
name_index: u2,
|
pub name_index: FromPool,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct Fieldref {
|
||||||
|
/// May be a class or interface type
|
||||||
|
pub class_index: FromPool,
|
||||||
|
/// Entry must be `NameAndType`
|
||||||
|
pub name_and_type_index: FromPool,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct MethodRef {
|
||||||
|
/// Must be a class type
|
||||||
|
pub class_index: FromPool,
|
||||||
|
/// Entry must be `NameAndType`
|
||||||
|
pub name_and_type_index: FromPool,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct InterfaceMethodref {
|
||||||
|
/// Must be an interface type
|
||||||
|
pub class_index: FromPool,
|
||||||
|
/// Entry must be `NameAndType`
|
||||||
|
pub name_and_type_index: FromPool,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct String {
|
||||||
/// Entry must be `Utf8`
|
/// Entry must be `Utf8`
|
||||||
descriptor_index: u2,
|
pub string_index: FromPool,
|
||||||
},
|
}
|
||||||
Utf8 {
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
tag: u1, // 1
|
pub struct Integer {
|
||||||
|
// Big endian
|
||||||
|
pub bytes: u4,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct Float {
|
||||||
|
/// IEEE 754 floating-point single format, big endian
|
||||||
|
pub bytes: u4,
|
||||||
|
}
|
||||||
|
/// 8 byte constants take up two spaces in the constant pool
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct Long {
|
||||||
|
/// Big endian
|
||||||
|
pub high_bytes: u4,
|
||||||
|
/// Big endian
|
||||||
|
pub low_bytes: u4,
|
||||||
|
}
|
||||||
|
/// 8 byte constants take up two spaces in the constant pool
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct Double {
|
||||||
|
/// IEEE 754 floating-point double format, big endian
|
||||||
|
pub high_bytes: u4,
|
||||||
|
/// IEEE 754 floating-point double format, big endian
|
||||||
|
pub low_bytes: u4,
|
||||||
|
}
|
||||||
|
/// Any field or method, without the class it belongs to
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct NameAndType {
|
||||||
|
/// Entry must be `Utf8`
|
||||||
|
pub name_index: FromPool,
|
||||||
|
/// Entry must be `Utf8`
|
||||||
|
pub descriptor_index: FromPool,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct Utf8 {
|
||||||
/// The length of the String. Not null-terminated.
|
/// The length of the String. Not null-terminated.
|
||||||
length: u2,
|
pub length: u2,
|
||||||
/// Contains modified UTF-8
|
/// Contains modified UTF-8
|
||||||
bytes: String,
|
pub bytes: std::string::String,
|
||||||
},
|
}
|
||||||
MethodHandle {
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
tag: u1, // 15
|
pub struct MethodHandle {
|
||||||
/// The kind of method handle (0-9)
|
/// The kind of method handle (0-9)
|
||||||
reference_kind: u1,
|
pub reference_kind: u1,
|
||||||
/// If the kind is 1-4, the entry must be `FieldRef`. If the kind is 5-8, the entry must be `MethodRef`
|
/// If the kind is 1-4, the entry must be `FieldRef`. If the kind is 5-8, the entry must be `MethodRef`
|
||||||
/// If the kind is 9, the entry must be `InterfaceMethodRef`
|
/// If the kind is 9, the entry must be `InterfaceMethodRef`
|
||||||
reference_index: u2,
|
pub reference_index: FromPool,
|
||||||
},
|
}
|
||||||
MethodType {
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
tag: u1, // 16
|
pub struct MethodType {
|
||||||
/// Entry must be `Utf8`
|
/// Entry must be `Utf8`
|
||||||
descriptor_index: u2,
|
pub descriptor_index: FromPool,
|
||||||
},
|
}
|
||||||
InvokeDynamic {
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
tag: u1, // 18
|
pub struct InvokeDynamic {
|
||||||
/// Must be a valid index into the `bootstrap_methods` array of the bootstrap method table of this class fiel
|
/// Must be a valid index into the `bootstrap_methods` array of the bootstrap method table of this class field
|
||||||
bootstrap_method_attr_index: u2,
|
pub bootstrap_method_attr_index: u2,
|
||||||
/// Entry must `NameAndType`
|
/// Entry must `NameAndType`
|
||||||
name_and_type_index: u2,
|
pub name_and_type_index: FromPool,
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about a field
|
/// Information about a field
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct FieldInfo {
|
pub struct FieldInfo {
|
||||||
pub access_flags: u2,
|
pub access_flags: u2,
|
||||||
pub name_index: u2,
|
pub name_index: FromPool,
|
||||||
pub descriptor_index: u2,
|
pub descriptor_index: FromPool,
|
||||||
pub attributes_count: u2,
|
pub attributes_count: u2,
|
||||||
pub attributes: Vec<AttributeInfo>,
|
pub attributes: Vec<AttributeInfo>,
|
||||||
}
|
}
|
||||||
|
|
@ -166,9 +220,9 @@ pub struct MethodInfo {
|
||||||
/// Mask of `MethodAccessFlag` used to denote access permissions
|
/// Mask of `MethodAccessFlag` used to denote access permissions
|
||||||
pub access_flags: u2,
|
pub access_flags: u2,
|
||||||
/// Index to the `constant_pool` of the method name, must be `Utf8`
|
/// Index to the `constant_pool` of the method name, must be `Utf8`
|
||||||
pub name_index: u2,
|
pub name_index: FromPool,
|
||||||
/// Index to the `constant_pool` of the method descriptor, must be `Utf8`
|
/// Index to the `constant_pool` of the method descriptor, must be `Utf8`
|
||||||
pub descriptor_index: u2,
|
pub descriptor_index: FromPool,
|
||||||
/// The amount of attributes for this method
|
/// The amount of attributes for this method
|
||||||
pub attributes_count: u2,
|
pub attributes_count: u2,
|
||||||
/// The attributes for this method
|
/// The attributes for this method
|
||||||
|
|
@ -183,7 +237,7 @@ pub struct MethodInfo {
|
||||||
/// _index: Index to the `constant_pool` table of any type
|
/// _index: Index to the `constant_pool` table of any type
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct AttributeInfo {
|
pub struct AttributeInfo {
|
||||||
pub attribute_name_index: u2,
|
pub attribute_name_index: FromPool,
|
||||||
pub attribute_length: u4,
|
pub attribute_length: u4,
|
||||||
/// The attribute value
|
/// The attribute value
|
||||||
pub inner: AttributeInfoInner,
|
pub inner: AttributeInfoInner,
|
||||||
|
|
@ -200,7 +254,7 @@ pub enum AttributeInfoInner {
|
||||||
/// Only on fields, the constant value of that field
|
/// Only on fields, the constant value of that field
|
||||||
ConstantValue {
|
ConstantValue {
|
||||||
/// Must be of type `Long`/`Float`/`Double`/`Integer`/`String`
|
/// Must be of type `Long`/`Float`/`Double`/`Integer`/`String`
|
||||||
constantvalue_index: u2,
|
constantvalue_index: FromPool,
|
||||||
},
|
},
|
||||||
/// Only on methods, contains JVM instructions and auxiliary information for a single method
|
/// Only on methods, contains JVM instructions and auxiliary information for a single method
|
||||||
Code {
|
Code {
|
||||||
|
|
@ -240,9 +294,9 @@ pub enum AttributeInfoInner {
|
||||||
/// Only on a `ClassFile`, required if it is local or anonymous
|
/// Only on a `ClassFile`, required if it is local or anonymous
|
||||||
EnclosingMethod {
|
EnclosingMethod {
|
||||||
/// Must be a `Class` constant, the innermost enclosing class
|
/// Must be a `Class` constant, the innermost enclosing class
|
||||||
class_index: u2,
|
class_index: FromPool,
|
||||||
/// Must be zero or `NameAndType`
|
/// Must be zero or `NameAndType`
|
||||||
method_index: u2,
|
method_index: FromPool,
|
||||||
},
|
},
|
||||||
/// Can be on `ClassFile`, `FieldInfo`,or `MethodInfo`.
|
/// Can be on `ClassFile`, `FieldInfo`,or `MethodInfo`.
|
||||||
/// Every generated class has to have this attribute or the `Synthetic` Accessor modifier
|
/// Every generated class has to have this attribute or the `Synthetic` Accessor modifier
|
||||||
|
|
@ -250,12 +304,12 @@ pub enum AttributeInfoInner {
|
||||||
/// Can be on `ClassFile`, `FieldInfo`,or `MethodInfo`. Records generic signature information
|
/// Can be on `ClassFile`, `FieldInfo`,or `MethodInfo`. Records generic signature information
|
||||||
Signature {
|
Signature {
|
||||||
/// Must be `Utf8`, and a Class/Method/Field signature
|
/// Must be `Utf8`, and a Class/Method/Field signature
|
||||||
signature_index: u2,
|
signature_index: FromPool,
|
||||||
},
|
},
|
||||||
/// Only on a `ClassFile`
|
/// Only on a `ClassFile`
|
||||||
SourceFile {
|
SourceFile {
|
||||||
/// Must be `Utf8`, the name of the source filed
|
/// Must be `Utf8`, the name of the source filed
|
||||||
sourcefile_index: u2,
|
sourcefile_index: FromPool,
|
||||||
},
|
},
|
||||||
/// Only on a `ClassFile`
|
/// Only on a `ClassFile`
|
||||||
SourceDebugExtension {
|
SourceDebugExtension {
|
||||||
|
|
@ -414,11 +468,11 @@ pub enum VerificationTypeInfo {
|
||||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
pub struct AttributeInnerClass {
|
pub struct AttributeInnerClass {
|
||||||
/// Must be a `Class`
|
/// Must be a `Class`
|
||||||
pub inner_class_info_index: u2,
|
pub inner_class_info_index: FromPool,
|
||||||
/// Must be 0 or a `Class`
|
/// Must be 0 or a `Class`
|
||||||
pub outer_class_info_index: u2,
|
pub outer_class_info_index: FromPool,
|
||||||
/// Must be 0 or `Utf8`
|
/// Must be 0 or `Utf8`
|
||||||
pub inner_class_name_index: u2,
|
pub inner_class_name_index: FromPool,
|
||||||
/// Must be a mask of `InnerClassAccessFlags`
|
/// Must be a mask of `InnerClassAccessFlags`
|
||||||
pub inner_class_access_flags: u2,
|
pub inner_class_access_flags: u2,
|
||||||
}
|
}
|
||||||
|
|
@ -440,9 +494,9 @@ pub struct AttributeLocalVariableTable {
|
||||||
/// The local variable must have a value between `start_pc` and `start_pc + length`
|
/// The local variable must have a value between `start_pc` and `start_pc + length`
|
||||||
pub length: u2,
|
pub length: u2,
|
||||||
/// Must be `Utf8`
|
/// Must be `Utf8`
|
||||||
pub name_index: u2,
|
pub name_index: FromPool,
|
||||||
/// Must be `Utf8`, field descriptor or field signature encoding the type
|
/// Must be `Utf8`, field descriptor or field signature encoding the type
|
||||||
pub descriptor_or_signature_index: u2,
|
pub descriptor_or_signature_index: FromPool,
|
||||||
/// The variable must be at `index` in the local variable array
|
/// The variable must be at `index` in the local variable array
|
||||||
pub index: u2,
|
pub index: u2,
|
||||||
}
|
}
|
||||||
|
|
@ -451,7 +505,7 @@ pub struct AttributeLocalVariableTable {
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct Annotation {
|
pub struct Annotation {
|
||||||
/// Must be `Utf8`
|
/// Must be `Utf8`
|
||||||
pub type_index: u2,
|
pub type_index: FromPool,
|
||||||
pub num_element_value_pairs: u2,
|
pub num_element_value_pairs: u2,
|
||||||
pub element_value_pairs: Vec<AnnotationElementValuePair>,
|
pub element_value_pairs: Vec<AnnotationElementValuePair>,
|
||||||
}
|
}
|
||||||
|
|
@ -462,7 +516,7 @@ pub struct Annotation {
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct AnnotationElementValuePair {
|
pub struct AnnotationElementValuePair {
|
||||||
/// Must be `Utf8`
|
/// Must be `Utf8`
|
||||||
pub element_name_index: u2,
|
pub element_name_index: FromPool,
|
||||||
pub element_name_name: AnnotationElementValue,
|
pub element_name_name: AnnotationElementValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -480,19 +534,19 @@ pub enum AnnotationElementValueValue {
|
||||||
/// If the tag is B, C, D, F, I, J, S, Z, or s.
|
/// If the tag is B, C, D, F, I, J, S, Z, or s.
|
||||||
ConstValueIndex {
|
ConstValueIndex {
|
||||||
/// Must be the matching constant pool entry
|
/// Must be the matching constant pool entry
|
||||||
index: u2,
|
index: FromPool,
|
||||||
},
|
},
|
||||||
/// If the tag is e
|
/// If the tag is e
|
||||||
EnumConstValue {
|
EnumConstValue {
|
||||||
/// Must be `Utf8`
|
/// Must be `Utf8`
|
||||||
type_name_index: u2,
|
type_name_index: FromPool,
|
||||||
/// Must be `Utf8`
|
/// Must be `Utf8`
|
||||||
const_name_index: u2,
|
const_name_index: FromPool,
|
||||||
},
|
},
|
||||||
/// If the tag is c
|
/// If the tag is c
|
||||||
ClassInfoIndex {
|
ClassInfoIndex {
|
||||||
/// Must be `Utf8`, for example Ljava/lang/Object; for Object
|
/// Must be `Utf8`, for example Ljava/lang/Object; for Object
|
||||||
index: u2,
|
index: FromPool,
|
||||||
},
|
},
|
||||||
/// If the tag is @
|
/// If the tag is @
|
||||||
AnnotationValue {
|
AnnotationValue {
|
||||||
|
|
@ -517,10 +571,10 @@ pub struct ParameterAnnotation {
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct BootstrapMethod {
|
pub struct BootstrapMethod {
|
||||||
/// Must be a `MethodHandle`
|
/// Must be a `MethodHandle`
|
||||||
pub bootstrap_method_ref: u2,
|
pub bootstrap_method_ref: FromPool,
|
||||||
pub num_bootstrap_arguments: 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`
|
/// Each argument is a cpool entry. The constants must be `String, Class, Integer, Long, Float, Double, MethodHandle, or MethodType`
|
||||||
pub bootstrap_arguments: Vec<u2>,
|
pub bootstrap_arguments: Vec<FromPool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/////// Access Flags
|
/////// Access Flags
|
||||||
|
|
|
||||||
|
|
@ -47,77 +47,101 @@ fn parse_empty_class() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parsed.constant_pool,
|
parsed.constant_pool,
|
||||||
vec![
|
vec![
|
||||||
CpInfo::MethodRef {
|
CpInfo {
|
||||||
tag: 0x0a,
|
tag: 0x0a,
|
||||||
class_index: 2,
|
inner: CpInfoInner::MethodRef(cp_info::MethodRef {
|
||||||
name_and_type_index: 3
|
class_index: 2.into(),
|
||||||
|
name_and_type_index: 3.into(),
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Class {
|
CpInfo {
|
||||||
tag: 7,
|
tag: 7,
|
||||||
name_index: 4
|
inner: CpInfoInner::Class(cp_info::Class {
|
||||||
|
name_index: 4.into(),
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::NameAndType {
|
CpInfo {
|
||||||
tag: 0xc,
|
tag: 0xc,
|
||||||
name_index: 5,
|
inner: CpInfoInner::NameAndType(cp_info::NameAndType {
|
||||||
descriptor_index: 6
|
name_index: 5.into(),
|
||||||
|
descriptor_index: 6.into(),
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Utf8 {
|
CpInfo {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
length: 0x10,
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: "java/lang/Object".to_string()
|
length: 0x10,
|
||||||
|
bytes: "java/lang/Object".to_string()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Utf8 {
|
CpInfo {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
length: 6,
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: "<init>".to_string()
|
length: 6,
|
||||||
|
bytes: "<init>".to_string()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Utf8 {
|
CpInfo {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
length: 3,
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: "()V".to_string()
|
length: 3,
|
||||||
|
bytes: "()V".to_string()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Class {
|
CpInfo {
|
||||||
tag: 7,
|
tag: 7,
|
||||||
name_index: 8
|
inner: CpInfoInner::Class(cp_info::Class {
|
||||||
|
name_index: 8.into(),
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Utf8 {
|
CpInfo {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
length: 4,
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: "Test".to_string()
|
length: 4,
|
||||||
|
bytes: "Test".to_string()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Utf8 {
|
CpInfo {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
length: 4,
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: "Code".to_string()
|
length: 4,
|
||||||
|
bytes: "Code".to_string()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Utf8 {
|
CpInfo {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
length: 15,
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: "LineNumberTable".to_string()
|
length: 15,
|
||||||
|
bytes: "LineNumberTable".to_string()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Utf8 {
|
CpInfo {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
length: 10,
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: "SourceFile".to_string()
|
length: 10,
|
||||||
|
bytes: "SourceFile".to_string()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
CpInfo::Utf8 {
|
CpInfo {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
length: 9,
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: "Test.java".to_string()
|
length: 9,
|
||||||
|
bytes: "Test.java".to_string()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(parsed.access_flags, 0x0021);
|
assert_eq!(parsed.access_flags, 0x0021);
|
||||||
assert_eq!(parsed.this_class, 7);
|
assert_eq!(parsed.this_class, 7.into());
|
||||||
assert_eq!(parsed.super_class, 2);
|
assert_eq!(parsed.super_class, 2.into());
|
||||||
assert_eq!(parsed.interfaces_count, 0);
|
assert_eq!(parsed.interfaces_count, 0);
|
||||||
assert_eq!(parsed.interfaces, vec![]);
|
assert_eq!(parsed.interfaces, vec![]);
|
||||||
assert_eq!(parsed.fields_count, 0);
|
assert_eq!(parsed.fields_count, 0);
|
||||||
assert_eq!(parsed.fields, vec![]);
|
assert_eq!(parsed.fields, vec![]);
|
||||||
assert_eq!(parsed.method_count, 1);
|
assert_eq!(parsed.method_count, 1);
|
||||||
assert_eq!(parsed.methods[0].access_flags, 1);
|
assert_eq!(parsed.methods[0].access_flags, 1);
|
||||||
assert_eq!(parsed.methods[0].name_index, 5);
|
assert_eq!(parsed.methods[0].name_index, 5.into());
|
||||||
assert_eq!(parsed.methods[0].descriptor_index, 6);
|
assert_eq!(parsed.methods[0].descriptor_index, 6.into());
|
||||||
assert_eq!(parsed.methods[0].attributes_count, 1);
|
assert_eq!(parsed.methods[0].attributes_count, 1);
|
||||||
//assert_eq!(parsed.methods[0].attributes[0].attribute_name_index, 9);
|
//assert_eq!(parsed.methods[0].attributes[0].attribute_name_index, 9);
|
||||||
//assert_eq!(parsed.methods[0].attributes[0].attribute_length, 0x1d);
|
//assert_eq!(parsed.methods[0].attributes[0].attribute_length, 0x1d);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue