restructure structure

This commit is contained in:
nora 2021-12-15 21:36:37 +01:00
parent 1a920ab9af
commit 1186e70e69
22 changed files with 196 additions and 24 deletions

View file

@ -1,2 +1,16 @@
[workspace]
members = ["crates/*"]
members = [
"cs_class_printer",
"cs_model",
"cs_parser",
"cs_vm",
]
[package]
name = "coldsquare"
version = "0.1.0"
edition = "2021"
[dependencies]
cs_class_printer = { path = "cs_class_printer" }
cs_parser = { path = "cs_parser" }

View file

@ -1,9 +1,9 @@
[package]
name = "file-info"
name = "cs_class_printer"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
file-parser = { path = "../file-parser" }
cs_parser = { path = "../cs_parser" }

View file

@ -0,0 +1,13 @@
use crate::ui::display_class;
use cs_parser::ClassFile;
mod ui;
/// Pretty-prints a class file
pub fn print(class_file: &ClassFile) {
let stdout = std::io::stdout();
if let Err(why) = display_class(stdout.lock(), class_file) {
eprintln!("{}", why);
}
}

View file

@ -1,4 +1,4 @@
use file_parser::ClassFile;
use cs_parser::ClassFile;
use std::io;
use std::io::Write;

View file

@ -1,5 +1,5 @@
[package]
name = "file-parser"
name = "cs_model"
version = "0.1.0"
edition = "2021"

View file

@ -1,5 +1,5 @@
[package]
name = "class-struct"
name = "cs_parser"
version = "0.1.0"
edition = "2021"

View file

@ -25,6 +25,7 @@ struct Data<'a> {
pointer: usize,
}
/// Parses the class file into a `ClassFile` structure
pub fn parse_class_file(data: &[u1]) -> Result<ClassFile> {
let mut data = Data::new(data);
ClassFile::parse(&mut data, &[])

View file

@ -125,6 +125,10 @@ macro_rules! impl_try_from_cp {
if index == 0 {
return Err(ParseErr("Index must not be 0".to_string()));
}
if info.len() == 0 {
return Ok(());
}
// todo this here might actually be an empty constant pool depending on whether is is still parsing the constant pool
// it needs to be checked after testing
// not now
@ -302,6 +306,9 @@ impl ValidateCpInfo for Utf8 {
if index == 0 {
return Err(ParseErr("Index must not be 0".to_string()));
}
if info.len() == 0 {
return Ok(());
}
match &info[index as usize - 1].inner {
CpInfoInner::Utf8(_) => Ok(()),
kind => Err(ParseErr(format!(

View file

@ -37,7 +37,7 @@ fn data_u4() {
#[test]
fn parse_empty_class() {
let class = include_bytes!("../../../testdata/Test.class");
let class = include_bytes!("../testdata/Test.class");
let parsed = parse_class_file(class).unwrap();
assert_eq!(parsed.minor_version, 0);
@ -139,7 +139,7 @@ fn parse_empty_class() {
#[test]
fn more_complex_file() {
let class = include_bytes!("../../../testdata/Test2.class");
let class = include_bytes!("../testdata/Test2.class");
let parsed = parse_class_file(class).unwrap();
assert_eq!(parsed.magic, 0xCAFEBABE);
}

BIN
cs_parser/testdata/Test.class vendored Normal file

Binary file not shown.

133
cs_parser/testdata/Test.class.txt vendored Normal file
View file

@ -0,0 +1,133 @@
Manually parsed by hand
hexdump -C Test.class
00000000 |ca fe ba be|00 00|00 3b |00 0d|0a.00 02.00 03|07. |.......;........|
00000010 00 04|0c.00 05.00 06|01 .00 10.6a 61 76 61 2f 6c |..........java/l|
00000020 61 6e 67 2f 4f 62 6a 65 63 74|01.00 06.3c 69 6e |ang/Object...<in|
00000030 69 74 3e|01.00 03.28 29 56|07.00 08|01.00 04.54 |it>...()V......T|
00000040 65 73 74|01.00 04.43 6f 64 65|01.00 0f.4c 69 6e |est...Code...Lin|
00000050 65 4e 75 6d 62 65 72 54 61 62 6c 65|01.00 0a.53 |eNumberTable...S|
00000060 6f 75 72 63 65 46 69 6c 65|01.00 09.54 65 73 74 |ourceFile...Test|
00000070 2e 6a 61 76 61|00 21|00 07|00 02|00 00|00 00|00 |.java.!.........|
00000080 01|00 01.00 05.00 06.00 01:00 09.00 00 00 1d.00 |................|
00000090 01.00 01.00 00 00 05.2a b7 00 01 b1.00 00.00 01: |.......*........|
000000a0 00 0a.00 00 00 06.00 01 :00 00.00 01|00 01|00 0b. |................|
000000b0 00 00 00 02.00 0c |......|
000000b6
Magic: ca fe ba be
Minor: 00 00
Major: 00 3b
CpCount: 00 0d (13) (13 - 1 = 12)
Cp: [
1: {
tag: 0a (10, MethodRef)
class_index: 00 02 (2)
name_and_type_index: 00 03
}
2: {
tag: 07 (7, Class)
name_index: 00 04 (4) (java/lang/Object)
}
3: {
tag: 0c (12, NameAndType)
name_index: 00 05 (05)
descriptor_index: 00 06
}
4: {
tag: 01 (1, Utf8)
length: 00 10 (16)
string: 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 (java/lang/Object)
}
5: {
tag: 01 (1, Utf8)
length: 00 06 (6)
string: 3c 69 6e 69 74 3e (<init>)
}
6: {
tag: 01 (1, Utf8)
length: 00 03 (3)
bytes: 28 29 56 (()V)
}
7: {
tag: 07 (7, Class)
name_index: 00 08 (8) (Test)
}
8: {
tag: 01 (1, Utf8)
length: 00 04 (4)
bytes: 54 65 73 74 (Test)
}
9: {
tag: 01 (1, Utf8)
length: 00 04 (4)
bytes: 43 6f 64 65 (Code)
}
10: {
tag: 01 (1, Utf8)
length: 00 0f (15)
bytes: 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65 (LineNumberTable)
}
11: {
tag: 01 (1, Utf8)
length: 00 0a (10)
bytes: 53 6f 75 72 63 65 46 69 6c 65 (SourceFile)
}
12: {
tag: 01 (1, Utf8)
length: 00 09 (9)
bytes: 54 65 73 74 2e 6a 61 76 61 (Test.java)
}
]
access_flags: 00 21
this_class: 00 07 (Test)
super_class: 00 02 (java/lang/Object)
interfaces_count: 00 00
interfaces: []
fields_count: 00 00
fields: []
methods_count: 00 01
methods: [
{
access_flags: 00 01
name_index: 00 05
descriptor_index: 00 06
attributes_count: 00 01
attributes: [
{
name_index: 00 09 (Code)
attribute_length: 00 00 00 1d (29)
max_stack: 00 01
max_locals: 00 01
code_length: 00 00 00 05
code: 2a b7 00 01 b1
exception_table_length: 00 00
exception_table: []
attributes_count: 00 01
attributes: [
{
attribute_name_index: 00 0a (LineNumberTable)
attribute_length: 00 00 00 06
line_number_table_length: 00 01
line_number_table: [
{
start_pc: 00 00
line_number: 00 01
}
]
}
]
}
]
}
]
attributes_count: 00 01
attributes: [
{
attribute_name_index: 00 0b (SourceFile)
attribute_length: 00 00 00 02
sourcefile_index: 00 0c
}
]

1
cs_parser/testdata/Test.java vendored Normal file
View file

@ -0,0 +1 @@
public class Test {}

BIN
cs_parser/testdata/Test2.class vendored Normal file

Binary file not shown.

13
cs_parser/testdata/Test2.java vendored Normal file
View file

@ -0,0 +1,13 @@
class Test2 {
int myField;
public static void main(String[] args) {
int i = 0;
i++;
new Test2().print(i);
}
void print(int i) {
System.out.println(i);
}
}

View file

@ -1,5 +1,5 @@
[package]
name = "machine"
name = "cs_vm"
version = "0.1.0"
edition = "2021"

View file

@ -58,6 +58,7 @@ mod tests {
use super::{LocalVariables, OperandStack};
#[test]
#[ignore]
fn operand_stack() {
let mut stack = OperandStack::new();

View file

@ -1,4 +0,0 @@
#!/bin/bash
cd crates/file-info
cargo run ../../"$1"

View file

@ -1,28 +1,21 @@
use crate::ui::display_class;
use file_parser::parse_class_file;
mod ui;
fn main() {
let file = std::env::args().nth(1).unwrap_or_else(|| {
eprintln!("No file provided");
std::process::exit(1);
});
let file = std::fs::read(file).unwrap_or_else(|_| {
let contents = std::fs::read(file).unwrap_or_else(|_| {
eprintln!("Could not read file");
std::process::exit(1);
});
let class_file = match parse_class_file(&file) {
let class_file = match cs_parser::parse_class_file(&contents) {
Ok(file) => file,
Err(err) => {
eprintln!("{}", err);
return;
}
};
let stdout = std::io::stdout();
if let Err(why) = display_class(stdout.lock(), &class_file) {
eprintln!("{}", why);
}
cs_class_printer::print(&class_file);
}