java.rs/src/classloader/io.rs
2023-11-27 22:12:31 +01:00

200 lines
5.2 KiB
Rust

use std::fs::{self};
use crate::vm::opcodes::Opcode;
use crate::vm::opcodes::Opcode::*;
use anyhow::{anyhow, Error};
#[cfg(target_family = "unix")]
pub const PATH_SEPARATOR: char = ':';
#[cfg(target_family = "windows")]
pub const PATH_SEPARATOR: char = ';';
/// resolves the actual path where the class file is found
/// for std lib there is a special case that resolves to the jmod
/// notation:
/// * [jmod]#classes/[package_path]/[class].class
/// * [jar/zip]#[package_path]/[class].class
/// * [dir]/[package_path]/[class].class
pub fn find_class(classpath: &Vec<String>, class_name: &str) -> Result<String, Error> {
if class_name.starts_with("java")
|| class_name.starts_with("sun/")
|| class_name.starts_with("com/sun/")
|| class_name.starts_with("jdk/")
{
let mut path: String = "jmods/java.base.jmod#classes/".into();
path.push_str(class_name);
path.push_str(".class");
return Ok(path);
}
for clp_entry in classpath {
if fs::metadata(clp_entry)?.is_dir() {
let mut maybe_path = clp_entry.clone();
maybe_path.push('/');
maybe_path.push_str(class_name);
maybe_path.push_str(".class");
if fs::metadata(&maybe_path)?.is_file() {
return Ok(maybe_path);
}
} else {
//TODO jar/zip files
}
}
Err(anyhow!("Class not found {}", class_name))
}
// methods to read values from big-endian binary data
pub(crate) fn read_u8(data: &[u8], pos: &mut usize) -> u8 {
*pos += 1;
u8::from_be_bytes(
data[*pos - 1..*pos]
.try_into()
.expect("slice with incorrect length"),
)
}
pub(crate) fn read_bytes(data: &[u8], pos: &mut usize, len: usize) -> Vec<u8> {
*pos += len;
data[*pos - len..*pos]
.try_into()
.expect("slice with incorrect length")
}
pub(crate) fn read_u16(data: &[u8], pos: &mut usize) -> u16 {
*pos += 2;
u16::from_be_bytes(
data[*pos - 2..*pos]
.try_into()
.expect("slice with incorrect length"),
)
}
pub(crate) fn read_i16(data: &[u8], pos: &mut usize) -> i16 {
*pos += 2;
i16::from_be_bytes(
data[*pos - 2..*pos]
.try_into()
.expect("slice with incorrect length"),
)
}
pub(crate) fn read_i32(data: &[u8], pos: &mut usize) -> i32 {
*pos += 4;
i32::from_be_bytes(
data[*pos - 4..*pos]
.try_into()
.expect("slice with incorrect length"),
)
}
pub(crate) fn read_u32(data: &[u8], pos: &mut usize) -> u32 {
*pos += 4;
u32::from_be_bytes(
data[*pos - 4..*pos]
.try_into()
.expect("slice with incorrect length"),
)
}
pub(crate) fn read_f32(data: &[u8], pos: &mut usize) -> f32 {
*pos += 4;
f32::from_be_bytes(
data[*pos - 4..*pos]
.try_into()
.expect("slice with incorrect length"),
)
}
pub(crate) fn read_i64(data: &[u8], pos: &mut usize) -> i64 {
*pos += 8;
i64::from_be_bytes(
data[*pos - 8..*pos]
.try_into()
.expect("slice with incorrect length"),
)
}
pub(crate) fn read_f64(data: &[u8], pos: &mut usize) -> f64 {
*pos += 8;
f64::from_be_bytes(
data[*pos - 8..*pos]
.try_into()
.expect("slice with incorrect length"),
)
}
pub(crate) fn read_tableswitch(data: &[u8], pos: &mut usize) -> Tableswitch {
while *pos % 4 != 0 {
*pos += 1;
}
let default = read_i32(data, pos);
let low = read_i32(data, pos);
let high = read_i32(data, pos);
let mut offsets = vec![];
for _ in low..=high {
offsets.push(read_i32(data, pos));
}
Tableswitch {
default,
low,
high,
offsets,
}
}
pub(crate) fn read_lookupswitch(data: &[u8], pos: &mut usize) -> Lookupswitch {
while *pos % 4 != 0 {
*pos += 1;
}
let default = read_i32(data, pos);
let npairs = read_i32(data, pos);
let mut match_offset_pairs = vec![];
for _ in 0..npairs {
match_offset_pairs.push((read_i32(data, pos), read_i32(data, pos)));
}
Lookupswitch {
default,
match_offset_pairs,
}
}
pub(crate) fn read_wide_opcode(data: &[u8], pos: &mut usize) -> Opcode {
let opcode = read_u8(data, pos);
if opcode == 132 {
WIDE_IINC(read_u16(data, pos), read_u16(data, pos))
} else {
let index = read_u16(data, pos);
match opcode {
21 => WIDE_ILOAD(index),
22 => WIDE_LLOAD(index),
23 => WIDE_FLOAD(index),
24 => WIDE_DLOAD(index),
25 => WIDE_ALOAD(index),
54 => WIDE_ISTORE(index),
55 => WIDE_LSTORE(index),
56 => WIDE_FSTORE(index),
57 => WIDE_DSTORE(index),
58 => WIDE_ASTORE(index),
169 => WIDE_RET(index),
_ => {
unreachable!("unknown opcode for WIDE")
}
}
}
}
#[derive(Clone, Debug)]
pub(crate) struct Tableswitch {
default: i32,
low: i32,
high: i32,
offsets: Vec<i32>,
}
#[derive(Clone, Debug)]
pub(crate) struct Lookupswitch {
default: i32,
match_offset_pairs: Vec<(i32, i32)>,
}