From 10f964a8f5031deeeab9ae9a4794c5480118101c Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Thu, 19 Aug 2021 22:07:48 +0200 Subject: [PATCH] parser seems to work kind of maybe --- src/parse/mod.rs | 47 +++++++++++++++++++++-------------------- src/parse/test.rs | 10 +++++++-- testdata/Test.class.txt | 4 ++-- testdata/Test2.java | 11 ++++++++++ 4 files changed, 45 insertions(+), 27 deletions(-) create mode 100644 testdata/Test2.java diff --git a/src/parse/mod.rs b/src/parse/mod.rs index c64cc94..d2f2211 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -9,15 +9,15 @@ pub struct ParseErr(String); pub type Result = std::result::Result; -#[derive(Copy, Clone)] +#[derive(Clone)] struct Data<'a> { data: &'a [u1], pointer: usize, } pub fn parse_class_file(data: &[u1]) -> Result { - let data = Data { data, pointer: 0 }; - ClassFile::parse(data) + let mut data = Data { data, pointer: 0 }; + ClassFile::parse(&mut data) } impl<'a> Data<'a> { @@ -67,12 +67,12 @@ impl<'a> Data<'a> { } trait Parse { - fn parse(data: Data) -> Result + fn parse(data: &mut Data) -> Result where Self: Sized; } -fn parse_vec>(data: Data, len: S) -> Result> { +fn parse_vec>(data: &mut Data, len: S) -> Result> { let len = len.into(); let mut vec = Vec::with_capacity(len); for _ in 0..len { @@ -84,7 +84,7 @@ fn parse_vec>(data: Data, len: S) -> Result> { macro_rules! parse_primitive { ($($value:ident),*) => { $(impl Parse for $value { - fn parse(mut data: Data) -> Result + fn parse(data: &mut Data) -> Result where Self: Sized, { @@ -97,7 +97,7 @@ macro_rules! parse_primitive { parse_primitive!(u1, u2, u4); impl Parse for ClassFile { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { let magic = data.u4()?; assert_eq!(magic, 0xCAFEBABE); let minor_version = data.u2()?; @@ -115,6 +115,7 @@ impl Parse for ClassFile { let methods = parse_vec(data, method_count)?; let attributes_count = data.u2()?; let attributes = parse_vec(data, attributes_count)?; + Ok(Self { magic, minor_version, @@ -137,7 +138,7 @@ impl Parse for ClassFile { } impl Parse for CpInfo { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { let tag = data.u1()?; Ok(match tag { @@ -212,7 +213,7 @@ impl Parse for CpInfo { } impl Parse for FieldInfo { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { access_flags: data.u2()?, name_index: data.u2()?, @@ -224,7 +225,7 @@ impl Parse for FieldInfo { } impl Parse for MethodInfo { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { access_flags: data.u2()?, name_index: data.u2()?, @@ -236,7 +237,7 @@ impl Parse for MethodInfo { } impl Parse for Attribute { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { attribute_name_index: data.u2()?, attribute_length: data.u4()?, @@ -246,7 +247,7 @@ impl Parse for Attribute { } impl Parse for AttributeCodeException { - fn parse(data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { start_pc: data.last_u2()?, end_pc: data.last_u2()?, @@ -257,7 +258,7 @@ impl Parse for AttributeCodeException { } impl Parse for StackMapFrame { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { let frame_type = data.u1()?; Ok(match frame_type { @@ -301,7 +302,7 @@ impl Parse for StackMapFrame { } impl Parse for VerificationTypeInfo { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { let tag = data.u1()?; Ok(match tag { 0 => Self::Top { tag }, @@ -328,7 +329,7 @@ impl Parse for VerificationTypeInfo { } impl Parse for AttributeInnerClass { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { inner_class_info_index: data.u2()?, outer_class_info_index: data.u2()?, @@ -339,7 +340,7 @@ impl Parse for AttributeInnerClass { } impl Parse for AttributeLineNumber { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { start_pc: data.u2()?, line_number: data.u2()?, @@ -348,7 +349,7 @@ impl Parse for AttributeLineNumber { } impl Parse for AttributeLocalVariableTable { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { start_pc: data.u2()?, length: data.u2()?, @@ -360,7 +361,7 @@ impl Parse for AttributeLocalVariableTable { } impl Parse for Annotation { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { type_index: data.u2()?, num_element_value_pairs: data.u2()?, @@ -370,7 +371,7 @@ impl Parse for Annotation { } impl Parse for AnnotationElementValuePair { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { element_name_index: data.u2()?, element_name_name: AnnotationElementValue::parse(data)?, @@ -379,7 +380,7 @@ impl Parse for AnnotationElementValuePair { } impl Parse for AnnotationElementValue { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { tag: data.u1()?, value: AnnotationElementValueValue::parse(data)?, @@ -388,7 +389,7 @@ impl Parse for AnnotationElementValue { } impl Parse for AnnotationElementValueValue { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { let tag = data.last_u1()? as char; Ok(match tag { 'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's' => { @@ -415,7 +416,7 @@ impl Parse for AnnotationElementValueValue { } impl Parse for ParameterAnnotation { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { num_annotations: data.u2()?, annotations: parse_vec(data, data.last_u2()?)?, @@ -424,7 +425,7 @@ impl Parse for ParameterAnnotation { } impl Parse for BootstrapMethod { - fn parse(mut data: Data) -> Result { + fn parse(data: &mut Data) -> Result { Ok(Self { bootstrap_method_ref: data.u2()?, num_bootstrap_arguments: data.u2()?, diff --git a/src/parse/test.rs b/src/parse/test.rs index 4b645bf..7bda087 100644 --- a/src/parse/test.rs +++ b/src/parse/test.rs @@ -38,7 +38,6 @@ fn data_u4() { #[test] fn parse_empty_class() { let class = include_bytes!("../../testdata/Test.class"); - println!("Starting test..."); let parsed = parse_class_file(class).unwrap(); assert_eq!(parsed.minor_version, 0); @@ -70,7 +69,7 @@ fn parse_empty_class() { CpInfo::Utf8 { tag: 1, length: 6, - bytes: "init".bytes().collect() + bytes: "".bytes().collect() }, CpInfo::Utf8 { 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_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); +} diff --git a/testdata/Test.class.txt b/testdata/Test.class.txt index 1fa0218..a0170df 100644 --- a/testdata/Test.class.txt +++ b/testdata/Test.class.txt @@ -25,7 +25,7 @@ Cp: [ 1: { tag: 0a (10, MethodRef) class_index: 00 02 (2) - name_and_type_index: 00 03 (2) + name_and_type_index: 00 03 } 2: { tag: 07 (7, Class) @@ -34,7 +34,7 @@ Cp: [ 3: { tag: 0c (12, NameAndType) name_index: 00 05 (05) - descriptor_index: 00 06 (6) + descriptor_index: 00 06 } 4: { tag: 01 (1, Utf8) diff --git a/testdata/Test2.java b/testdata/Test2.java new file mode 100644 index 0000000..0feea96 --- /dev/null +++ b/testdata/Test2.java @@ -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); + } +} \ No newline at end of file