mirror of
https://github.com/Noratrieb/coldsquare.git
synced 2026-01-17 09:55:08 +01:00
parsing
This commit is contained in:
parent
48a7270bbb
commit
b07a20566c
12 changed files with 514 additions and 158 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1 +1,6 @@
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
|
||||||
/target
|
/target
|
||||||
|
|
||||||
|
*.class
|
||||||
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
|
|
@ -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/
|
|
||||||
11
.idea/coldsquare.iml
generated
11
.idea/coldsquare.iml
generated
|
|
@ -1,11 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="CPP_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
6
.idea/discord.xml
generated
6
.idea/discord.xml
generated
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DiscordProjectSettings">
|
|
||||||
<option name="show" value="PROJECT_FILES" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
11
.idea/misc.xml
generated
11
.idea/misc.xml
generated
|
|
@ -1,11 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="MavenImportPreferences">
|
|
||||||
<option name="generalSettings">
|
|
||||||
<MavenGeneralSettings>
|
|
||||||
<option name="mavenHome" value="C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2020.2\plugins\maven\lib\maven3" />
|
|
||||||
</MavenGeneralSettings>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Haskell Tool Stack" project-jdk-type="Haskell Tool Stack SDK" />
|
|
||||||
</project>
|
|
||||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
|
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/coldsquare.iml" filepath="$PROJECT_DIR$/.idea/coldsquare.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
|
|
@ -4,9 +4,7 @@ pub struct OperandStack {
|
||||||
|
|
||||||
impl OperandStack {
|
impl OperandStack {
|
||||||
pub fn new() -> OperandStack {
|
pub fn new() -> OperandStack {
|
||||||
OperandStack {
|
OperandStack { vec: vec![] }
|
||||||
vec: vec![],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop(&mut self) -> u32 {
|
pub fn pop(&mut self) -> u32 {
|
||||||
|
|
@ -24,14 +22,12 @@ impl OperandStack {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LocalVariables {
|
pub struct LocalVariables {
|
||||||
vec: Vec<u32>
|
vec: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalVariables {
|
impl LocalVariables {
|
||||||
pub fn new(size: usize) -> LocalVariables {
|
pub fn new(size: usize) -> LocalVariables {
|
||||||
LocalVariables {
|
LocalVariables { vec: vec![0; size] }
|
||||||
vec: vec![0; size]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store(&mut self, address: u8, value: u32) {
|
pub fn store(&mut self, address: u8, value: u32) {
|
||||||
|
|
@ -49,12 +45,11 @@ impl LocalVariables {
|
||||||
pub fn load2(&self, address: u8) -> (u32, u32) {
|
pub fn load2(&self, address: u8) -> (u32, u32) {
|
||||||
(self.vec[address as usize], self.vec[address as usize + 1])
|
(self.vec[address as usize], self.vec[address as usize + 1])
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::model::{LocalVariables, OperandStack};
|
use crate::execute::model::{LocalVariables, OperandStack};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn operand_stack() {
|
fn operand_stack() {
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,8 @@
|
||||||
mod parse;
|
use crate::parse::{ClassFile, ParseErr};
|
||||||
|
|
||||||
mod execute;
|
mod execute;
|
||||||
|
mod parse;
|
||||||
|
|
||||||
|
pub fn parse_class_file(file: Vec<u8>) -> Result<ClassFile, ParseErr> {
|
||||||
|
parse::parse_class_file(file)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
use coldsquare::parse_class_file;
|
||||||
|
|
||||||
fn main() {
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
441
src/parse/mod.rs
441
src/parse/mod.rs
|
|
@ -1,14 +1,22 @@
|
||||||
use crate::parse::model::{u1, u2, u4, ClassFile, CpInfo};
|
|
||||||
|
|
||||||
mod model;
|
mod model;
|
||||||
|
pub use model::*;
|
||||||
|
use std::path::Prefix::Verbatim;
|
||||||
|
|
||||||
struct ParseErr;
|
#[derive(Debug)]
|
||||||
|
pub struct ParseErr;
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, ParseErr>;
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
data: Vec<u1>,
|
data: Vec<u1>,
|
||||||
pointer: usize,
|
pointer: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_class_file(data: Vec<u1>) -> Result<ClassFile> {
|
||||||
|
let mut data = Data { data, pointer: 0 };
|
||||||
|
ClassFile::parse(&mut data)
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Vec<u8>> for Data {
|
impl From<Vec<u8>> for Data {
|
||||||
fn from(data: Vec<u1>) -> Self {
|
fn from(data: Vec<u1>) -> Self {
|
||||||
Self { data, pointer: 0 }
|
Self { data, pointer: 0 }
|
||||||
|
|
@ -16,67 +24,422 @@ impl From<Vec<u8>> for Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
fn u1(&mut self) -> Result<u1, ParseErr> {
|
fn u1(&mut self) -> Result<u1> {
|
||||||
let item = self.data.get(self.pointer).cloned();
|
let item = self.data.get(self.pointer).cloned();
|
||||||
self.pointer += 1;
|
self.pointer += 1;
|
||||||
item.ok_or(ParseErr)
|
item.ok_or(ParseErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u2(&mut self) -> Result<u2, ParseErr> {
|
fn u2(&mut self) -> Result<u2> {
|
||||||
Ok(((self.u1()? as u2) << 8) | self.u1() as u2)
|
Ok(((self.u1()? as u2) << 8) | self.u1()? as u2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u4(&mut self) -> Result<u4, ParseErr> {
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last_u1(&mut self) -> Result<u1, ParseErr> {
|
fn last_u1(&self) -> Result<u1> {
|
||||||
self.data.get(self.pointer - 1).cloned().ok_or(ParseErr)
|
self.data.get(self.pointer - 1).cloned().ok_or(ParseErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last_u2(&mut self) -> Result<u2, ParseErr> {
|
fn last_u2(&self) -> Result<u2> {
|
||||||
let last2u1 = self.data.get(self.pointer - 2).cloned().ok_or(ParseErr);
|
let last2u1 = self.data.get(self.pointer - 2).cloned().ok_or(ParseErr)?;
|
||||||
Ok(((self.last_u1()? as u2) << 8) | last2u1 as u2)
|
Ok(((last2u1 as u2) << 8) | self.last_u1()? as u2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn last_u4(&self) -> Result<u4> {
|
||||||
|
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 {
|
pub trait Parse {
|
||||||
fn parse(data: &mut Data) -> Result<Self, ParseErr>;
|
fn parse(data: &mut Data) -> Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ParseVec<T> {
|
pub trait ParseVec<T> {
|
||||||
fn parse_vec<T: Parse>(data: &mut Data, len: usize) -> Result<Self, ParseErr>;
|
fn parse_vec(data: &mut Data, len: usize) -> Result<Self>
|
||||||
}
|
where
|
||||||
|
Self: Sized;
|
||||||
impl Parse for ClassFile {
|
|
||||||
fn parse(data: &mut Data) -> Result<Self, ParseErr> {
|
|
||||||
Ok(Self {
|
|
||||||
magic: data.u4()?,
|
|
||||||
minor_version: data.u2()?,
|
|
||||||
major_version: data.u2()?,
|
|
||||||
constant_pool_count: data.u2()?,
|
|
||||||
constant_pool: Vec::parse_vec::<CpInfo>(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![],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Parse> ParseVec<T> for Vec<T> {
|
impl<T: Parse> ParseVec<T> for Vec<T> {
|
||||||
fn parse_vec<T: Parse>(data: &mut Data, len: usize) -> Result<Self, ParseErr> {
|
fn parse_vec(data: &mut Data, len: usize) -> Result<Self> {
|
||||||
let mut vec = Vec::with_capacity(len);
|
let mut vec = Vec::with_capacity(len);
|
||||||
for i in 0..len {
|
for _ in 0..len {
|
||||||
vec.push(T::parse(data)?);
|
vec.push(T::parse(data)?);
|
||||||
}
|
}
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! parse_primitive {
|
||||||
|
($value:ident) => {
|
||||||
|
impl Parse for $value {
|
||||||
|
fn parse(data: &mut Data) -> Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
data.$value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_primitive!(u1);
|
||||||
|
parse_primitive!(u2);
|
||||||
|
parse_primitive!(u4);
|
||||||
|
|
||||||
|
impl Parse for ClassFile {
|
||||||
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
|
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<Self> {
|
||||||
|
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<Self> {
|
||||||
|
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<Self> {
|
||||||
|
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<Self> {
|
||||||
|
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<Self> {
|
||||||
|
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<Self> {
|
||||||
|
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<Self>
|
||||||
|
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<Self> {
|
||||||
|
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<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
start_pc: data.u2()?,
|
||||||
|
line_number: data.u2()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for AttributeLocalVariableTable {
|
||||||
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
|
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<Self> {
|
||||||
|
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<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
element_name_index: data.u2()?,
|
||||||
|
element_name_name: AnnotationElementValue::parse(data)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for AnnotationElementValue {
|
||||||
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
tag: data.u1()?,
|
||||||
|
value: AnnotationElementValueValue::parse(data)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for AnnotationElementValueValue {
|
||||||
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
|
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<Self> {
|
||||||
|
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<Self> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,44 +14,46 @@ pub type u4 = u32;
|
||||||
///
|
///
|
||||||
/// # Represents a .class file
|
/// # Represents a .class file
|
||||||
///
|
///
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct ClassFile {
|
pub struct ClassFile {
|
||||||
/// Magic number identifying the format (= 0xCAFEBABE)
|
/// Magic number identifying the format (= 0xCAFEBABE)
|
||||||
pub(crate) magic: u4,
|
pub magic: u4,
|
||||||
/// The version of the class file (.X)
|
/// The version of the class file (.X)
|
||||||
pub(crate) minor_version: u2,
|
pub minor_version: u2,
|
||||||
/// The version of the class file (X.)
|
/// The version of the class file (X.)
|
||||||
pub(crate) major_version: u2,
|
pub major_version: u2,
|
||||||
/// Number of entries in the constant pool + 1
|
/// 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
|
/// The constant pool. Indexed from 1 to constant_pool_count - 1
|
||||||
pub(crate) constant_pool: Vec<CpInfo>,
|
pub constant_pool: Vec<CpInfo>,
|
||||||
/// Mask of `ClassAccessFlag` used to denote access permissions
|
/// 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`
|
/// 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
|
/// 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
|
/// 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`
|
/// Each entry must be a valid index into the `constant_pool` table. The entry must be a `ConstantClassInfo`
|
||||||
pub(crate) interfaces: Vec<u2>,
|
pub interfaces: Vec<u2>,
|
||||||
/// The number of fields in the `fields` table
|
/// 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
|
/// All fields of the class. Contains only fields of the class itself
|
||||||
pub(crate) fields: Vec<FieldInfo>,
|
pub fields: Vec<FieldInfo>,
|
||||||
/// The number of methods in `methods`
|
/// 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
|
/// All methods of the class. If it's neither Native nor Abstract, the implementation has to be provided too
|
||||||
pub(crate) methods: Vec<MethodInfo>,
|
pub methods: Vec<MethodInfo>,
|
||||||
/// The number of attributes in `attributes`
|
/// The number of attributes in `attributes`
|
||||||
pub(crate) attributes_count: u2,
|
pub attributes_count: u2,
|
||||||
/// All attributes of the class
|
/// All attributes of the class
|
||||||
pub(crate) attributes: Vec<AttributeInfo>,
|
pub attributes: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A constant from the constant pool
|
/// A constant from the constant pool
|
||||||
/// 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)]
|
||||||
pub enum CpInfo {
|
pub enum CpInfo {
|
||||||
Class {
|
Class {
|
||||||
tag: u1, // 7
|
tag: u1, // 7
|
||||||
|
|
@ -139,7 +141,7 @@ pub enum CpInfo {
|
||||||
descriptor_index: u2,
|
descriptor_index: u2,
|
||||||
},
|
},
|
||||||
InvokeDynamic {
|
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
|
/// Must be a valid index into the `bootstrap_methods` array of the bootstrap method table of this class fiel
|
||||||
bootstrap_method_attr_index: u2,
|
bootstrap_method_attr_index: u2,
|
||||||
/// Entry must `NameAndType`
|
/// Entry must `NameAndType`
|
||||||
|
|
@ -148,26 +150,36 @@ pub enum CpInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about a field
|
/// Information about a field
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct FieldInfo {
|
pub struct FieldInfo {
|
||||||
access_flags: u2,
|
pub access_flags: u2,
|
||||||
name_index: u2,
|
pub name_index: u2,
|
||||||
descriptor_index: u2,
|
pub descriptor_index: u2,
|
||||||
attributes_count: u2,
|
pub attributes_count: u2,
|
||||||
attributes: Vec<AttributeInfo>,
|
pub attributes: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about a method
|
/// Information about a method
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct MethodInfo {
|
pub struct MethodInfo {
|
||||||
/// Mask of `MethodAccessFlag` used to denote access permissions
|
/// 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`
|
/// 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`
|
/// 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
|
/// The amount of attributes for this method
|
||||||
attributes_count: u2,
|
pub attributes_count: u2,
|
||||||
/// The attributes for this method
|
/// The attributes for this method
|
||||||
attributes: Vec<AttributeInfo>,
|
pub attributes: Vec<Attribute>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See `AttributeInfo`
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
|
pub struct Attribute {
|
||||||
|
pub attribute_name_index: u2,
|
||||||
|
pub attribute_length: u4,
|
||||||
|
pub attribute_content: Vec<u1>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about an attribute
|
/// 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
|
/// `attribute_length`: The length of the subsequent bytes, does not include the first 6
|
||||||
///
|
///
|
||||||
/// _index: Index to the `constant_pool` table of any type
|
/// _index: Index to the `constant_pool` table of any type
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
|
#[allow(dead_code)] // todo yeah lol
|
||||||
pub enum AttributeInfo {
|
pub enum AttributeInfo {
|
||||||
/// Only on fields, the constant value of that field
|
/// Only on fields, the constant value of that field
|
||||||
ConstantValue {
|
ConstantValue {
|
||||||
|
|
@ -202,7 +216,7 @@ pub enum AttributeInfo {
|
||||||
exception_table: Vec<AttributeCodeException>,
|
exception_table: Vec<AttributeCodeException>,
|
||||||
attributes_count: u2,
|
attributes_count: u2,
|
||||||
/// The attributes of the code
|
/// The attributes of the code
|
||||||
attributes: Vec<AttributeInfo>,
|
attributes: Vec<Attribute>,
|
||||||
},
|
},
|
||||||
/// Only on the `Code` attribute, used for verification
|
/// Only on the `Code` attribute, used for verification
|
||||||
/// May be implicit on version >= 50.0, with no entries
|
/// 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
|
/// An exception handler in the JVM bytecode array
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct AttributeCodeException {
|
pub struct AttributeCodeException {
|
||||||
/// The ranges in the code in which the handler is active. Must be a valid index into the code array.
|
/// 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
|
/// 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 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
|
/// 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
|
/// 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`
|
/// 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`
|
/// 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
|
/// 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
|
/// Has a offset_delta, the offset is calculated by adding offset_delta + 1 to the previous offset
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum StackMapFrame {
|
pub enum StackMapFrame {
|
||||||
/// Exactly the same locals as the previous frame and zero stack items, offset_delta is frame_type
|
/// Exactly the same locals as the previous frame and zero stack items, offset_delta is frame_type
|
||||||
SameFrame {
|
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
|
/// Exactly the same locals as the previous frame and 1 stack item, offset_delta is given explicitly
|
||||||
SameLocals1StackItemFrameExtended {
|
SameLocals1StackItemFrameExtended {
|
||||||
frame_type: u1, // 257
|
frame_type: u1, // 247
|
||||||
offset_delta: u2,
|
offset_delta: u2,
|
||||||
stack: VerificationTypeInfo,
|
stack: VerificationTypeInfo,
|
||||||
},
|
},
|
||||||
|
|
@ -397,6 +413,7 @@ pub enum StackMapFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A stack value/local variable type `StackMapFrame`
|
/// A stack value/local variable type `StackMapFrame`
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum VerificationTypeInfo {
|
pub enum VerificationTypeInfo {
|
||||||
Top {
|
Top {
|
||||||
tag: u1, // 0
|
tag: u1, // 0
|
||||||
|
|
@ -431,64 +448,71 @@ pub enum VerificationTypeInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct for the `AttributeInfo::InnerClasses`
|
/// A struct for the `AttributeInfo::InnerClasses`
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct AttributeInnerClass {
|
pub struct AttributeInnerClass {
|
||||||
/// Must be a `Class`
|
/// Must be a `Class`
|
||||||
inner_class_info_index: u2,
|
pub inner_class_info_index: u2,
|
||||||
/// Must be 0 or a `Class`
|
/// Must be 0 or a `Class`
|
||||||
outer_class_info_index: u2,
|
pub outer_class_info_index: u2,
|
||||||
/// Must be 0 or `Utf8`
|
/// Must be 0 or `Utf8`
|
||||||
inner_class_name_index: u2,
|
pub inner_class_name_index: u2,
|
||||||
/// Must be a mask of `InnerClassAccessFlags`
|
/// Must be a mask of `InnerClassAccessFlags`
|
||||||
inner_class_access_flags: u2,
|
pub inner_class_access_flags: u2,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Line number information for `AttributeInfo::LineNumberTable`
|
/// Line number information for `AttributeInfo::LineNumberTable`
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct AttributeLineNumber {
|
pub struct AttributeLineNumber {
|
||||||
/// Index into the code array where a new line in the source begins
|
/// 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
|
/// The line number in the source file
|
||||||
line_number: u2,
|
pub line_number: u2,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Local variable information for `AttributeInfo::LocalVariableTable` and `AttributeInfo::LocalVariableTypeTable`
|
/// Local variable information for `AttributeInfo::LocalVariableTable` and `AttributeInfo::LocalVariableTypeTable`
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct AttributeLocalVariableTable {
|
pub struct AttributeLocalVariableTable {
|
||||||
/// The local variable must have a value between `start_pc` and `start_pc + length`. Must be a valid opcode
|
/// 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`
|
/// The local variable must have a value between `start_pc` and `start_pc + length`
|
||||||
length: u2,
|
pub length: u2,
|
||||||
/// Must be `Utf8`
|
/// Must be `Utf8`
|
||||||
name_index: u2,
|
pub name_index: u2,
|
||||||
/// Must be `Utf8`, field descriptor or field signature encoding the type
|
/// 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
|
/// The variable must be at `index` in the local variable array
|
||||||
index: u2,
|
pub index: u2,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A runtime-visible annotation to the program
|
/// A runtime-visible annotation to the program
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct Annotation {
|
pub struct Annotation {
|
||||||
/// Must be `Utf8`
|
/// Must be `Utf8`
|
||||||
type_index: u2,
|
pub type_index: u2,
|
||||||
num_element_value_pairs: u2,
|
pub num_element_value_pairs: u2,
|
||||||
element_value_pairs: Vec<AnnotationElementValuePair>,
|
pub element_value_pairs: Vec<AnnotationElementValuePair>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// these type names have just become java at this point. no shame.
|
// these type names have just become java at this point. no shame.
|
||||||
|
|
||||||
/// A element-value pair in the `Annotation`
|
/// A element-value pair in the `Annotation`
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct AnnotationElementValuePair {
|
pub struct AnnotationElementValuePair {
|
||||||
/// Must be `Utf8`
|
/// Must be `Utf8`
|
||||||
element_name_index: u2,
|
pub element_name_index: u2,
|
||||||
element_name_name: AnnotationElementValue,
|
pub element_name_name: AnnotationElementValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The value of an `AnnotationElementValuePair`
|
/// The value of an `AnnotationElementValuePair`
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct AnnotationElementValue {
|
pub struct AnnotationElementValue {
|
||||||
/// B, C, D, F, I, J, S, Z or s, e, c, @,
|
/// B, C, D, F, I, J, S, Z or s, e, c, @,
|
||||||
tag: u1,
|
pub tag: u1,
|
||||||
value: AnnotationElementValueValue,
|
pub value: AnnotationElementValueValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The value of a `AnnotationElementValue`
|
/// The value of a `AnnotationElementValue`
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum AnnotationElementValueValue {
|
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 {
|
||||||
|
|
@ -520,24 +544,27 @@ pub enum AnnotationElementValueValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in `AttributeInfo::RuntimeVisibleParameterAnnotations`
|
/// Used in `AttributeInfo::RuntimeVisibleParameterAnnotations`
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct ParameterAnnotation {
|
pub struct ParameterAnnotation {
|
||||||
num_annotations: u2,
|
pub num_annotations: u2,
|
||||||
annotations: Vec<Annotation>,
|
pub annotations: Vec<Annotation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in `AttributeInfo::BootstrapMethods `
|
/// Used in `AttributeInfo::BootstrapMethods `
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct BootstrapMethod {
|
pub struct BootstrapMethod {
|
||||||
/// Must be a `MethodHandle`
|
/// Must be a `MethodHandle`
|
||||||
bootstrap_method_ref: u2,
|
pub bootstrap_method_ref: u2,
|
||||||
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`
|
||||||
bootstrap_arguments: Vec<u2>,
|
pub bootstrap_arguments: Vec<u2>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/////// Access Flags
|
/////// Access Flags
|
||||||
|
|
||||||
/// Access Flags of a class
|
/// Access Flags of a class
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum ClassAccessFlag {
|
pub enum ClassAccessFlag {
|
||||||
/// Declared public; may be accessed from outside its package.
|
/// Declared public; may be accessed from outside its package.
|
||||||
Public = 0x0001,
|
Public = 0x0001,
|
||||||
|
|
@ -559,6 +586,7 @@ pub enum ClassAccessFlag {
|
||||||
|
|
||||||
/// Access Flags of a method
|
/// Access Flags of a method
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum MethodAccessFlag {
|
pub enum MethodAccessFlag {
|
||||||
// Declared public; may be accessed from outside its package.
|
// Declared public; may be accessed from outside its package.
|
||||||
PUBLIC = 0x0001,
|
PUBLIC = 0x0001,
|
||||||
|
|
@ -588,6 +616,7 @@ pub enum MethodAccessFlag {
|
||||||
|
|
||||||
/// Access flags for an inner class
|
/// Access flags for an inner class
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum InnerClassAccessFlags {
|
pub enum InnerClassAccessFlags {
|
||||||
/// Marked or implicitly public in source.
|
/// Marked or implicitly public in source.
|
||||||
PUBLIC = 0x0001,
|
PUBLIC = 0x0001,
|
||||||
|
|
@ -613,6 +642,7 @@ pub enum InnerClassAccessFlags {
|
||||||
|
|
||||||
/// Access flags for a field
|
/// Access flags for a field
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum FieldAccessFlags {
|
pub enum FieldAccessFlags {
|
||||||
/// Declared public; may be accessed from outside its package.
|
/// Declared public; may be accessed from outside its package.
|
||||||
PUBLIC = 0x0001,
|
PUBLIC = 0x0001,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue