parser seems to work kind of maybe

This commit is contained in:
nora 2021-08-19 22:07:48 +02:00
parent 5d435a208c
commit 10f964a8f5
4 changed files with 45 additions and 27 deletions

View file

@ -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()?,

View file

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

View file

@ -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
View 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);
}
}