Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/cargo/zip-2.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Pfarrer authored Jun 4, 2024
2 parents 76f1f71 + 3fbd844 commit c82b5cd
Show file tree
Hide file tree
Showing 35 changed files with 900 additions and 393 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ members = [
"model",
"loader",
"parser",
# "vm",
"vm",
"rt",
"cli",
]
]
2 changes: 1 addition & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ rt = { path = "../rt" }

clap = { version = "3.1.2", features = ["derive"] }
prettytable-rs = "0.10"
env_logger = "0.10"
env_logger = "0.11"
anyhow = { version = "1.0", features = ["backtrace"] }
49 changes: 23 additions & 26 deletions model/src/class.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
use enumset::{EnumSet, EnumSetType};

#[derive(EnumSetType, Debug)]
pub enum ClassAccessFlag {
Public,
Private,
Protected,
Final,
Super,
Interface,
Abstract,
Synthetic,
Annotation,
Enum,
}

#[derive(Default, Clone, Debug)]
pub struct JvmClass {
pub version: ClassVersion,
Expand All @@ -35,8 +21,7 @@ pub struct ClassVersion {
pub minor: u16,
}

#[derive(Default, Clone, Debug)]
pub struct ClassConstants(pub Vec<ClassConstant>);
pub type ClassConstants = Vec<ClassConstant>;

#[derive(Clone, Debug)]
pub enum ClassConstant {
Expand All @@ -56,9 +41,6 @@ pub enum ClassConstant {
// class_name, method_name, method_signature
InterfaceMethodref(String, String, MethodSignature),

// class_index, name_and_type_index
// InterfaceMethodref(u16, u16),

// string_index
String(String),

Expand Down Expand Up @@ -92,6 +74,21 @@ pub enum ClassConstant {
InvokeDynamic(u16, String, MethodSignature),
}

#[derive(EnumSetType, Debug)]
pub enum ClassAccessFlag {
Public,
Private,
Protected,
Final,
Super,
Interface,
Abstract,
Synthetic,
Annotation,
Enum,
Module,
}

#[derive(EnumSetType, Debug)]
pub enum FieldAccessFlag {
/// Declared public; may be accesse from outside its package.
Expand Down Expand Up @@ -188,19 +185,17 @@ pub type ClassAttributes = Vec<ClassAttribute>;

#[derive(Clone, Debug)]
pub enum ClassAttribute {
Code(CodeAttribute),
Code(Code),
LineNumberTable(Vec<SourceLineNumber>),
SourceFile(u16),
SourceFile(String),
Exceptions(Vec<u16>),
Signature(u16),
ConstantValue(u16),
ConstantValue(ClassConstant),
BootstrapMethods(Vec<BootstrapMethod>),
Deprecated,
NotImplemented,
}

#[derive(Default, Clone, Debug)]
pub struct CodeAttribute {
pub struct Code {
pub max_stack: u16,
pub max_locals: u16,
pub code: Vec<u8>,
Expand All @@ -213,7 +208,9 @@ pub struct ExceptionTable {
pub start_pc: u16,
pub end_pc: u16,
pub handler_pc: u16,
pub catch_type: u16,
/// Some(String): String identifies the class of exceptions that this exception handler is designated to catch.
/// None: this exception handler is called for all exceptions.
pub catch_type: Option<String>,
}

#[derive(Default, Clone, Debug)]
Expand Down
38 changes: 38 additions & 0 deletions model/src/class_constant_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use anyhow::{bail, Context, Result};

use crate::{class::ClassConstant, prelude::ClassConstants};

impl ClassConstant {
pub fn ok_and_utf8_or(&self) -> Result<&String> {
match self {
&ClassConstant::Utf8(ref string) => Ok(string),
it => bail!("Expected Utf8 but found {:?}", it),
}
}

pub fn ok_and_class_or(&self) -> Result<&String> {
match self {
&ClassConstant::Class(ref string) => Ok(string),
it => bail!("Expected Class but found {:?}", it),
}
}
}

pub trait ClassConstantAccessor {
fn get_utf8_or(&self, idx: usize) -> Result<&String>;
fn get_class_or(&self, idx: usize) -> Result<&String>;
}

impl ClassConstantAccessor for ClassConstants {
fn get_utf8_or(&self, idx: usize) -> Result<&String> {
self.get(idx)
.context(format!("get constant with index {}", idx))?
.ok_and_utf8_or()
}

fn get_class_or(&self, idx: usize) -> Result<&String> {
self.get(idx)
.context(format!("get constant with index {}", idx))?
.ok_and_class_or()
}
}
30 changes: 0 additions & 30 deletions model/src/class_impl.rs

This file was deleted.

7 changes: 4 additions & 3 deletions model/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
pub mod api;
pub mod class;
pub mod class_impl;
pub mod class_constant_impl;

pub mod prelude {
pub use crate::class::{ClassAttribute, JvmClass};
}
pub use crate::class::{*};
pub use crate::class_constant_impl;
}
1 change: 0 additions & 1 deletion parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ edition = "2021"
[dependencies]
model = { path = "../model" }

classfile-parser = { git = "https://github.com/Pfarrer/classfile-parser.git" }
enumset = "1.1"
anyhow = "1.0"
11 changes: 0 additions & 11 deletions parser/src/attributes.rs

This file was deleted.

56 changes: 56 additions & 0 deletions parser/src/attributes/code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use std::io::Read;

use anyhow::Result;
use class_constant_impl::ClassConstantAccessor;
use model::prelude::*;

use crate::util;
use crate::attributes;

pub fn parse<T: Read>(reader: &mut T, constants: &ClassConstants) -> Result<Code> {
/*let attribute_length = */util::read_u32(reader)?;

let max_stack = util::read_u16(reader)?;
let max_locals = util::read_u16(reader)?;

let code_length = util::read_u32(reader)? as usize;
let code = util::read_raw(reader, code_length)?;

let exception_table = parse_exception_table(reader, constants)?;
let attributes = attributes::parse(reader, constants)?;

Ok(Code {
max_stack,
max_locals,
code,
exception_table,
attributes,
})
}

fn parse_exception_table<T: Read>(reader: &mut T, constants: &ClassConstants) -> Result<Vec<ExceptionTable>> {
let exception_table_length = util::read_u16(reader)? as usize;
let mut entries = Vec::with_capacity(exception_table_length);

for _ in 0..exception_table_length {
entries.push(ExceptionTable {
start_pc: util::read_u16(reader)?,
end_pc: util::read_u16(reader)?,
handler_pc: util::read_u16(reader)?,
catch_type: parse_exception_table_catch_type(reader, constants)?,
})
}

Ok(entries)
}

fn parse_exception_table_catch_type<T: Read>(reader: &mut T, constants: &ClassConstants) -> Result<Option<String>> {
let class_name_index = util::read_u16(reader)? as usize;
let class_name = if class_name_index == 0 {
None
} else {
Some(constants.get_class_or(class_name_index)?.clone())
};

Ok(class_name)
}
16 changes: 16 additions & 0 deletions parser/src/attributes/constant_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use std::io::Read;

use anyhow::Context;
use anyhow::Result;
use model::prelude::*;

use crate::util;

pub fn parse<T: Read>(reader: &mut T, constants: &ClassConstants) -> Result<ClassConstant> {
/*let attribute_length = */util::read_u32(reader)?;

let constant_index = util::read_u16(reader)? as usize;
let constant = constants.get(constant_index).context(format!("get constant with index {constant_index}"))?.clone();

Ok(constant)
}
57 changes: 57 additions & 0 deletions parser/src/attributes/local_variable_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::io::Read;

use anyhow::Result;
use class_constant_impl::ClassConstantAccessor;
use model::prelude::*;

use crate::util;
use crate::attributes;

pub fn parse<T: Read>(reader: &mut T, constants: &ClassConstants) -> Result<Vec<LocalVariableTable>> {
let _attribute_length = util::read_u32(reader)?;
let local_variable_table_length = util::read_u16(reader)? as usize;

let max_stack = util::read_u16(reader)?;
let max_locals = util::read_u16(reader)?;

let code_length = util::read_u32(reader)? as usize;
let code = util::read_raw(reader, code_length)?;

let exception_table = parse_exception_table(reader, constants)?;
let attributes = attributes::parse(reader, constants)?;

Ok(Code {
max_stack,
max_locals,
code,
exception_table,
attributes,
})
}

fn parse_exception_table<T: Read>(reader: &mut T, constants: &ClassConstants) -> Result<Vec<ExceptionTable>> {
let exception_table_length = util::read_u16(reader)? as usize;
let mut entries = Vec::with_capacity(exception_table_length);

for _ in 0..exception_table_length {
entries.push(ExceptionTable {
start_pc: util::read_u16(reader)?,
end_pc: util::read_u16(reader)?,
handler_pc: util::read_u16(reader)?,
catch_type: parse_exception_table_catch_type(reader, constants)?,
})
}

Ok(entries)
}

fn parse_exception_table_catch_type<T: Read>(reader: &mut T, constants: &ClassConstants) -> Result<Option<String>> {
let class_name_index = util::read_u16(reader)? as usize;
let class_name = if class_name_index == 0 {
None
} else {
Some(constants.get_class_or(class_name_index)?.clone())
};

Ok(class_name)
}
Loading

0 comments on commit c82b5cd

Please sign in to comment.