rusty-jvm 0.5.0

An implementation of a Java Virtual Machine (JVM).
Documentation
use crate::vm::error::Result;
use crate::vm::exception::helpers::{throw_file_not_found_exception, throw_ioexception};
use crate::vm::exception::throwing_result::ThrowingResult;
use crate::vm::heap::heap::with_heap_write_lock;
use crate::vm::helper::i64_to_vec;
use crate::vm::stack::stack_frame::StackFrames;
use crate::vm::system_native::platform_file::Mode::Read;
use crate::vm::system_native::platform_file::PlatformFile;
use crate::vm::system_native::string::get_utf8_string_by_ref;
use crate::{throw_and_return, unwrap_or_return_err, unwrap_result_or_return_default};
use std::fs::OpenOptions;
use std::io;
use std::io::{Read as IoRead, Seek};

pub(crate) fn file_input_stream_open0_wrp(
    args: &[i32],
    stack_frames: &mut StackFrames,
) -> Result<Vec<i32>> {
    let obj_ref = args[0];
    let string_ref = args[1];
    unwrap_result_or_return_default!(open0(obj_ref, string_ref, stack_frames), vec![]);
    Ok(vec![])
}

fn open0(obj_ref: i32, file_name_ref: i32, stack_frames: &mut StackFrames) -> ThrowingResult<()> {
    let file_name = unwrap_or_return_err!(get_utf8_string_by_ref(file_name_ref));
    match OpenOptions::new().read(true).open(&file_name) {
        Ok(file) => {
            let metadata = unwrap_or_return_err!(file.metadata());
            if metadata.is_dir() {
                let error = io::Error::new(io::ErrorKind::IsADirectory, "Is a directory");
                throw_and_return!(throw_file_not_found_exception(
                    file_name_ref,
                    &error.to_string(),
                    stack_frames
                ))
            }

            unwrap_or_return_err!(PlatformFile::set_raw_id(obj_ref, file, Read));
            ThrowingResult::ok(())
        }
        Err(e) => {
            let message = e.to_string();
            throw_and_return!(throw_file_not_found_exception(
                file_name_ref,
                &message,
                stack_frames
            ));
        }
    }
}

pub(crate) fn file_input_stream_length0_wrp(
    args: &[i32],
    stack_frames: &mut StackFrames,
) -> Result<Vec<i32>> {
    let obj_ref = args[0];
    let len = unwrap_result_or_return_default!(length0(obj_ref, stack_frames), vec![]);
    Ok(i64_to_vec(len))
}
fn length0(obj_ref: i32, stack_frames: &mut StackFrames) -> ThrowingResult<i64> {
    let file = match PlatformFile::get_by_raw_id(obj_ref, Read, stack_frames) {
        ThrowingResult::Result(result) => unwrap_or_return_err!(result),
        ThrowingResult::ExceptionThrown => return ThrowingResult::ExceptionThrown,
    };
    let metadata = match file.metadata() {
        Ok(m) => m,
        Err(e) => throw_and_return!(throw_ioexception(&e.to_string(), stack_frames)),
    };
    ThrowingResult::ok(metadata.len() as i64)
}

pub(crate) fn file_input_stream_position0_wrp(
    args: &[i32],
    stack_frames: &mut StackFrames,
) -> Result<Vec<i32>> {
    let obj_ref = args[0];
    let len = unwrap_result_or_return_default!(position0(obj_ref, stack_frames), vec![]);
    Ok(i64_to_vec(len))
}
fn position0(obj_ref: i32, stack_frames: &mut StackFrames) -> ThrowingResult<i64> {
    let mut file = match PlatformFile::get_by_raw_id(obj_ref, Read, stack_frames) {
        ThrowingResult::Result(result) => unwrap_or_return_err!(result),
        ThrowingResult::ExceptionThrown => return ThrowingResult::ExceptionThrown,
    };
    let pos = match file.stream_position() {
        Ok(p) => p,
        Err(e) => throw_and_return!(throw_ioexception(&e.to_string(), stack_frames)),
    };
    ThrowingResult::ok(pos as i64)
}

pub(crate) fn file_input_stream_available0_wrp(
    args: &[i32],
    stack_frames: &mut StackFrames,
) -> Result<Vec<i32>> {
    let obj_ref = args[0];
    let available = unwrap_result_or_return_default!(available0(obj_ref, stack_frames), vec![]);
    Ok(vec![available])
}
fn available0(obj_ref: i32, stack_frames: &mut StackFrames) -> ThrowingResult<i32> {
    let mut file = match PlatformFile::get_by_raw_id(obj_ref, Read, stack_frames) {
        ThrowingResult::Result(result) => unwrap_or_return_err!(result),
        ThrowingResult::ExceptionThrown => return ThrowingResult::ExceptionThrown,
    };
    let current_pos = match file.stream_position() {
        Ok(p) => p,
        Err(e) => throw_and_return!(throw_ioexception(&e.to_string(), stack_frames)),
    };
    let metadata = match file.metadata() {
        Ok(m) => m,
        Err(e) => throw_and_return!(throw_ioexception(&e.to_string(), stack_frames)),
    };
    let file_size = metadata.len();
    if file_size < current_pos {
        return ThrowingResult::ok(0);
    }
    let available = file_size - current_pos;
    let available = unwrap_or_return_err!(i32::try_from(available));
    ThrowingResult::ok(available)
}

pub(crate) fn file_input_stream_read_bytes_wrp(
    args: &[i32],
    stack_frames: &mut StackFrames,
) -> Result<Vec<i32>> {
    let obj_ref = args[0];
    let bytes_ref = args[1];
    let off = args[2];
    let len = args[3];
    let read_bytes = unwrap_result_or_return_default!(
        read_bytes(obj_ref, bytes_ref, off, len, stack_frames),
        vec![]
    );
    Ok(vec![read_bytes])
}
fn read_bytes(
    obj_ref: i32,
    bytes_ref: i32,
    off: i32,
    len: i32,
    stack_frames: &mut StackFrames,
) -> ThrowingResult<i32> {
    let mut file = match PlatformFile::get_by_raw_id(obj_ref, Read, stack_frames) {
        ThrowingResult::Result(result) => unwrap_or_return_err!(result),
        ThrowingResult::ExceptionThrown => return ThrowingResult::ExceptionThrown,
    };
    let mut buffer = vec![0u8; len as usize];
    let read_bytes = match file.read(&mut buffer) {
        Ok(n) => n,
        Err(e) => throw_and_return!(throw_ioexception(&e.to_string(), stack_frames)),
    };
    let array = with_heap_write_lock(|heap| heap.get_entire_array(bytes_ref));
    let mut array = unwrap_or_return_err!(array);

    for i in 0..read_bytes {
        unwrap_or_return_err!(array.set_value(off + i as i32, vec![buffer[i] as i8 as i32]));
    }

    unwrap_or_return_err!(with_heap_write_lock(
        |heap| heap.set_entire_array(bytes_ref, array)
    ));

    ThrowingResult::ok(read_bytes as i32)
}

pub(crate) fn file_input_stream_read0_wrp(
    args: &[i32],
    stack_frames: &mut StackFrames,
) -> Result<Vec<i32>> {
    let obj_ref = args[0];
    let read = unwrap_result_or_return_default!(read0(obj_ref, stack_frames), vec![]);
    Ok(vec![read])
}
fn read0(obj_ref: i32, stack_frames: &mut StackFrames) -> ThrowingResult<i32> {
    let mut file = match PlatformFile::get_by_raw_id(obj_ref, Read, stack_frames) {
        ThrowingResult::Result(result) => unwrap_or_return_err!(result),
        ThrowingResult::ExceptionThrown => return ThrowingResult::ExceptionThrown,
    };
    let mut buffer = [0u8; 1];
    let read_bytes = match file.read(&mut buffer) {
        Ok(n) => n,
        Err(e) => throw_and_return!(throw_ioexception(&e.to_string(), stack_frames)),
    };
    if read_bytes == 0 {
        return ThrowingResult::ok(-1);
    }
    ThrowingResult::ok(buffer[0] as i32)
}

pub(crate) fn file_input_stream_is_regular_file0_wrp(
    args: &[i32],
    stack_frames: &mut StackFrames,
) -> Result<Vec<i32>> {
    let _obj_ref = args[0];
    let fd_ref = args[1];
    let regular = unwrap_result_or_return_default!(is_regular_file0(fd_ref, stack_frames), vec![]);
    Ok(vec![if regular { 1 } else { 0 }])
}
fn is_regular_file0(fd_ref: i32, stack_frames: &mut StackFrames) -> ThrowingResult<bool> {
    let file = match PlatformFile::get_by_fd(fd_ref, stack_frames) {
        ThrowingResult::Result(result) => unwrap_or_return_err!(result),
        ThrowingResult::ExceptionThrown => return ThrowingResult::ExceptionThrown,
    };
    let metadata = match file.metadata() {
        Ok(m) => m,
        Err(e) => throw_and_return!(throw_ioexception(&e.to_string(), stack_frames)),
    };

    ThrowingResult::ok(metadata.is_file())
}