mirror of
https://github.com/Noratrieb/coldsquare.git
synced 2026-01-14 16:35:10 +01:00
parser seems to work kind of maybe
This commit is contained in:
parent
5d435a208c
commit
10f964a8f5
4 changed files with 45 additions and 27 deletions
|
|
@ -9,15 +9,15 @@ pub struct ParseErr(String);
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, ParseErr>;
|
pub type Result<T> = std::result::Result<T, ParseErr>;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Clone)]
|
||||||
struct Data<'a> {
|
struct Data<'a> {
|
||||||
data: &'a [u1],
|
data: &'a [u1],
|
||||||
pointer: usize,
|
pointer: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_class_file(data: &[u1]) -> Result<ClassFile> {
|
pub fn parse_class_file(data: &[u1]) -> Result<ClassFile> {
|
||||||
let data = Data { data, pointer: 0 };
|
let mut data = Data { data, pointer: 0 };
|
||||||
ClassFile::parse(data)
|
ClassFile::parse(&mut data)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Data<'a> {
|
impl<'a> Data<'a> {
|
||||||
|
|
@ -67,12 +67,12 @@ impl<'a> Data<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Parse {
|
trait Parse {
|
||||||
fn parse(data: Data) -> Result<Self>
|
fn parse(data: &mut Data) -> Result<Self>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_vec<T: Parse, S: Into<usize>>(data: Data, len: S) -> Result<Vec<T>> {
|
fn parse_vec<T: Parse, S: Into<usize>>(data: &mut Data, len: S) -> Result<Vec<T>> {
|
||||||
let len = len.into();
|
let len = len.into();
|
||||||
let mut vec = Vec::with_capacity(len);
|
let mut vec = Vec::with_capacity(len);
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
|
|
@ -84,7 +84,7 @@ fn parse_vec<T: Parse, S: Into<usize>>(data: Data, len: S) -> Result<Vec<T>> {
|
||||||
macro_rules! parse_primitive {
|
macro_rules! parse_primitive {
|
||||||
($($value:ident),*) => {
|
($($value:ident),*) => {
|
||||||
$(impl Parse for $value {
|
$(impl Parse for $value {
|
||||||
fn parse(mut data: Data) -> Result<Self>
|
fn parse(data: &mut Data) -> Result<Self>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
|
@ -97,7 +97,7 @@ macro_rules! parse_primitive {
|
||||||
parse_primitive!(u1, u2, u4);
|
parse_primitive!(u1, u2, u4);
|
||||||
|
|
||||||
impl Parse for ClassFile {
|
impl Parse for ClassFile {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
let magic = data.u4()?;
|
let magic = data.u4()?;
|
||||||
assert_eq!(magic, 0xCAFEBABE);
|
assert_eq!(magic, 0xCAFEBABE);
|
||||||
let minor_version = data.u2()?;
|
let minor_version = data.u2()?;
|
||||||
|
|
@ -115,6 +115,7 @@ impl Parse for ClassFile {
|
||||||
let methods = parse_vec(data, method_count)?;
|
let methods = parse_vec(data, method_count)?;
|
||||||
let attributes_count = data.u2()?;
|
let attributes_count = data.u2()?;
|
||||||
let attributes = parse_vec(data, attributes_count)?;
|
let attributes = parse_vec(data, attributes_count)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
magic,
|
magic,
|
||||||
minor_version,
|
minor_version,
|
||||||
|
|
@ -137,7 +138,7 @@ impl Parse for ClassFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for CpInfo {
|
impl Parse for CpInfo {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
let tag = data.u1()?;
|
let tag = data.u1()?;
|
||||||
|
|
||||||
Ok(match tag {
|
Ok(match tag {
|
||||||
|
|
@ -212,7 +213,7 @@ impl Parse for CpInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for FieldInfo {
|
impl Parse for FieldInfo {
|
||||||
fn parse(mut data: 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.u2()?,
|
||||||
|
|
@ -224,7 +225,7 @@ impl Parse for FieldInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for MethodInfo {
|
impl Parse for MethodInfo {
|
||||||
fn parse(mut data: 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.u2()?,
|
||||||
|
|
@ -236,7 +237,7 @@ impl Parse for MethodInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Attribute {
|
impl Parse for Attribute {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
attribute_name_index: data.u2()?,
|
attribute_name_index: data.u2()?,
|
||||||
attribute_length: data.u4()?,
|
attribute_length: data.u4()?,
|
||||||
|
|
@ -246,7 +247,7 @@ impl Parse for Attribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeCodeException {
|
impl Parse for AttributeCodeException {
|
||||||
fn parse(data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
start_pc: data.last_u2()?,
|
start_pc: data.last_u2()?,
|
||||||
end_pc: data.last_u2()?,
|
end_pc: data.last_u2()?,
|
||||||
|
|
@ -257,7 +258,7 @@ impl Parse for AttributeCodeException {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for StackMapFrame {
|
impl Parse for StackMapFrame {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
let frame_type = data.u1()?;
|
let frame_type = data.u1()?;
|
||||||
|
|
||||||
Ok(match frame_type {
|
Ok(match frame_type {
|
||||||
|
|
@ -301,7 +302,7 @@ impl Parse for StackMapFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for VerificationTypeInfo {
|
impl Parse for VerificationTypeInfo {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
let tag = data.u1()?;
|
let tag = data.u1()?;
|
||||||
Ok(match tag {
|
Ok(match tag {
|
||||||
0 => Self::Top { tag },
|
0 => Self::Top { tag },
|
||||||
|
|
@ -328,7 +329,7 @@ impl Parse for VerificationTypeInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeInnerClass {
|
impl Parse for AttributeInnerClass {
|
||||||
fn parse(mut data: 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.u2()?,
|
||||||
outer_class_info_index: data.u2()?,
|
outer_class_info_index: data.u2()?,
|
||||||
|
|
@ -339,7 +340,7 @@ impl Parse for AttributeInnerClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeLineNumber {
|
impl Parse for AttributeLineNumber {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
start_pc: data.u2()?,
|
start_pc: data.u2()?,
|
||||||
line_number: data.u2()?,
|
line_number: data.u2()?,
|
||||||
|
|
@ -348,7 +349,7 @@ impl Parse for AttributeLineNumber {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeLocalVariableTable {
|
impl Parse for AttributeLocalVariableTable {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
start_pc: data.u2()?,
|
start_pc: data.u2()?,
|
||||||
length: data.u2()?,
|
length: data.u2()?,
|
||||||
|
|
@ -360,7 +361,7 @@ impl Parse for AttributeLocalVariableTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Annotation {
|
impl Parse for Annotation {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
type_index: data.u2()?,
|
type_index: data.u2()?,
|
||||||
num_element_value_pairs: data.u2()?,
|
num_element_value_pairs: data.u2()?,
|
||||||
|
|
@ -370,7 +371,7 @@ impl Parse for Annotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AnnotationElementValuePair {
|
impl Parse for AnnotationElementValuePair {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
element_name_index: data.u2()?,
|
element_name_index: data.u2()?,
|
||||||
element_name_name: AnnotationElementValue::parse(data)?,
|
element_name_name: AnnotationElementValue::parse(data)?,
|
||||||
|
|
@ -379,7 +380,7 @@ impl Parse for AnnotationElementValuePair {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AnnotationElementValue {
|
impl Parse for AnnotationElementValue {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
tag: data.u1()?,
|
tag: data.u1()?,
|
||||||
value: AnnotationElementValueValue::parse(data)?,
|
value: AnnotationElementValueValue::parse(data)?,
|
||||||
|
|
@ -388,7 +389,7 @@ impl Parse for AnnotationElementValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AnnotationElementValueValue {
|
impl Parse for AnnotationElementValueValue {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
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' => {
|
||||||
|
|
@ -415,7 +416,7 @@ impl Parse for AnnotationElementValueValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ParameterAnnotation {
|
impl Parse for ParameterAnnotation {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
num_annotations: data.u2()?,
|
num_annotations: data.u2()?,
|
||||||
annotations: parse_vec(data, data.last_u2()?)?,
|
annotations: parse_vec(data, data.last_u2()?)?,
|
||||||
|
|
@ -424,7 +425,7 @@ impl Parse for ParameterAnnotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BootstrapMethod {
|
impl Parse for BootstrapMethod {
|
||||||
fn parse(mut data: Data) -> Result<Self> {
|
fn parse(data: &mut Data) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
bootstrap_method_ref: data.u2()?,
|
bootstrap_method_ref: data.u2()?,
|
||||||
num_bootstrap_arguments: data.u2()?,
|
num_bootstrap_arguments: data.u2()?,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ fn data_u4() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_empty_class() {
|
fn parse_empty_class() {
|
||||||
let class = include_bytes!("../../testdata/Test.class");
|
let class = include_bytes!("../../testdata/Test.class");
|
||||||
println!("Starting test...");
|
|
||||||
let parsed = parse_class_file(class).unwrap();
|
let parsed = parse_class_file(class).unwrap();
|
||||||
|
|
||||||
assert_eq!(parsed.minor_version, 0);
|
assert_eq!(parsed.minor_version, 0);
|
||||||
|
|
@ -70,7 +69,7 @@ fn parse_empty_class() {
|
||||||
CpInfo::Utf8 {
|
CpInfo::Utf8 {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
length: 6,
|
length: 6,
|
||||||
bytes: "init".bytes().collect()
|
bytes: "<init>".bytes().collect()
|
||||||
},
|
},
|
||||||
CpInfo::Utf8 {
|
CpInfo::Utf8 {
|
||||||
tag: 1,
|
tag: 1,
|
||||||
|
|
@ -123,3 +122,10 @@ fn parse_empty_class() {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn more_complex_file() {
|
||||||
|
let class = include_bytes!("../../testdata/Test2.class");
|
||||||
|
let parsed = parse_class_file(class).unwrap();
|
||||||
|
assert_eq!(parsed.magic, 0xCAFEBABE);
|
||||||
|
}
|
||||||
|
|
|
||||||
4
testdata/Test.class.txt
vendored
4
testdata/Test.class.txt
vendored
|
|
@ -25,7 +25,7 @@ Cp: [
|
||||||
1: {
|
1: {
|
||||||
tag: 0a (10, MethodRef)
|
tag: 0a (10, MethodRef)
|
||||||
class_index: 00 02 (2)
|
class_index: 00 02 (2)
|
||||||
name_and_type_index: 00 03 (2)
|
name_and_type_index: 00 03
|
||||||
}
|
}
|
||||||
2: {
|
2: {
|
||||||
tag: 07 (7, Class)
|
tag: 07 (7, Class)
|
||||||
|
|
@ -34,7 +34,7 @@ Cp: [
|
||||||
3: {
|
3: {
|
||||||
tag: 0c (12, NameAndType)
|
tag: 0c (12, NameAndType)
|
||||||
name_index: 00 05 (05)
|
name_index: 00 05 (05)
|
||||||
descriptor_index: 00 06 (6)
|
descriptor_index: 00 06
|
||||||
}
|
}
|
||||||
4: {
|
4: {
|
||||||
tag: 01 (1, Utf8)
|
tag: 01 (1, Utf8)
|
||||||
|
|
|
||||||
11
testdata/Test2.java
vendored
Normal file
11
testdata/Test2.java
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
class Test2 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int i = 0;
|
||||||
|
i++;
|
||||||
|
print(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print(int i) {
|
||||||
|
System.out.println(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue