Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ impl BufferedOutputStream {
length: i32,
) -> Result<()> {
tracing::debug!("java.io.BufferedOutputStream::write({this:?}, {bytes:?}, {offset}, {length})");
if bytes.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let source_length = jvm.array_length(&bytes).await? as i32;
if offset < 0 || length < 0 || offset > source_length - length {
Expand Down
22 changes: 20 additions & 2 deletions rustjava-runtime/src/classes/java/io/data_input_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,18 @@ impl DataInputStream {

async fn read_utf_from_input(jvm: &Jvm, _: &mut RuntimeContext, input: ClassInstanceRef<DataInput>) -> Result<ClassInstanceRef<String>> {
tracing::debug!("java.io.DataInputStream::readUTF({input:?})");
if input.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}
jvm.invoke_virtual(&input, &input.class_definition().name(), "readUTF", "()Ljava/lang/String;", ())
.await
}

async fn read_fully(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, b: ClassInstanceRef<Array<i8>>) -> Result<()> {
tracing::debug!("java.io.DataInputStream::readFully({this:?}, {b:?})");
if b.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let length = jvm.array_length(&b).await?;

Expand All @@ -239,6 +245,9 @@ impl DataInputStream {
len: i32,
) -> Result<()> {
tracing::debug!("java.io.DataInputStream::readFully({this:?}, {b:?}, {off}, {len})");
if b.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let mut read = 0;
while read < len {
Expand All @@ -257,14 +266,23 @@ impl DataInputStream {
async fn skip_bytes(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, n: i32) -> Result<i32> {
tracing::debug!("java.io.DataInputStream::skipBytes({this:?}, {n:?})");

let r#in = jvm.get_field(&this, "java/io/DataInputStream", "in", "Ljava/io/InputStream;").await?;
if n <= 0 {
return Ok(0);
}
let r#in: ClassInstanceRef<InputStream> = jvm.get_field(&this, "java/io/DataInputStream", "in", "Ljava/io/InputStream;").await?;
if r#in.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
let skipped: i64 = jvm.invoke_virtual(&r#in, "java/io/InputStream", "skip", "(J)J", (n as i64,)).await?;

Ok(skipped as _)
}

async fn read_required_byte(jvm: &Jvm, this: &ClassInstanceRef<Self>) -> Result<u8> {
let r#in = jvm.get_field(this, "java/io/DataInputStream", "in", "Ljava/io/InputStream;").await?;
let r#in: ClassInstanceRef<InputStream> = jvm.get_field(this, "java/io/DataInputStream", "in", "Ljava/io/InputStream;").await?;
if r#in.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
let value: i32 = jvm.invoke_virtual(&r#in, "java/io/InputStream", "read", "()I", ()).await?;
if value == -1 {
return Err(jvm.exception("java/io/EOFException", "End of stream").await);
Expand Down
65 changes: 55 additions & 10 deletions rustjava-runtime/src/classes/java/io/data_output_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ impl DataOutputStream {
async fn write(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, b: i32) -> Result<()> {
tracing::debug!("java.io.DataOutputStream::write({this:?}, {b:?})");

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
let _: () = jvm.invoke_virtual(&out, "java/io/OutputStream", "write", "(I)V", (b,)).await?;

Ok(())
Expand All @@ -114,7 +117,10 @@ impl DataOutputStream {
async fn write_byte(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, v: i32) -> Result<()> {
tracing::debug!("java.io.DataOutputStream::writeByte({this:?}, {v:?})");

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
let _: () = jvm.invoke_virtual(&out, "java/io/OutputStream", "write", "(I)V", (v,)).await?;

Ok(())
Expand All @@ -137,7 +143,10 @@ impl DataOutputStream {
let mut byte_array = jvm.instantiate_array("B", bytes.len() as _).await?;
jvm.store_array(&mut byte_array, 0, cast_vec::<u8, i8>(bytes.to_vec())).await?;

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
let _: () = jvm.invoke_virtual(&out, "java/io/OutputStream", "write", "([B)V", (byte_array,)).await?;

Ok(())
Expand All @@ -156,7 +165,10 @@ impl DataOutputStream {
let mut byte_array = jvm.instantiate_array("B", bytes.len() as _).await?;
jvm.store_array(&mut byte_array, 0, cast_vec::<u8, i8>(bytes.to_vec())).await?;

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
let _: () = jvm.invoke_virtual(&out, "java/io/OutputStream", "write", "([B)V", (byte_array,)).await?;

Ok(())
Expand All @@ -169,7 +181,10 @@ impl DataOutputStream {
let mut byte_array = jvm.instantiate_array("B", bytes.len() as _).await?;
jvm.store_array(&mut byte_array, 0, cast_vec::<u8, i8>(bytes.to_vec())).await?;

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
let _: () = jvm.invoke_virtual(&out, "java/io/OutputStream", "write", "([B)V", (byte_array,)).await?;

Ok(())
Expand All @@ -189,23 +204,38 @@ impl DataOutputStream {

async fn write_bytes(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, s: ClassInstanceRef<String>) -> Result<()> {
tracing::debug!("java.io.DataOutputStream::writeBytes({this:?}, {s:?})");
if s.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let chars: ClassInstanceRef<Array<JavaChar>> = jvm.invoke_virtual(&s, "java/lang/String", "toCharArray", "()[C", ()).await?;
let length = jvm.array_length(&chars).await?;
let chars: Vec<JavaChar> = jvm.load_array(&chars, 0, length).await?;
if chars.is_empty() {
return Ok(());
}
let mut bytes = jvm.instantiate_array("B", chars.len()).await?;
jvm.store_array(&mut bytes, 0, chars.into_iter().map(|value| value as i8)).await?;

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
jvm.invoke_virtual(&out, "java/io/OutputStream", "write", "([B)V", (bytes,)).await
}

async fn write_chars(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, s: ClassInstanceRef<String>) -> Result<()> {
tracing::debug!("java.io.DataOutputStream::writeChars({this:?}, {s:?})");
if s.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let chars: ClassInstanceRef<Array<JavaChar>> = jvm.invoke_virtual(&s, "java/lang/String", "toCharArray", "()[C", ()).await?;
let length = jvm.array_length(&chars).await?;
let chars: Vec<JavaChar> = jvm.load_array(&chars, 0, length).await?;
if chars.is_empty() {
return Ok(());
}
let mut data = Vec::with_capacity(chars.len() * 2);
for value in chars {
data.push((value >> 8) as i8);
Expand All @@ -215,12 +245,18 @@ impl DataOutputStream {
let mut bytes = jvm.instantiate_array("B", data.len()).await?;
jvm.store_array(&mut bytes, 0, data).await?;

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
jvm.invoke_virtual(&out, "java/io/OutputStream", "write", "([B)V", (bytes,)).await
}

async fn write_utf(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, s: ClassInstanceRef<String>) -> Result<()> {
tracing::debug!("java.io.DataOutputStream::writeUTF({this:?}, {s:?})");
if s.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let chars: ClassInstanceRef<Array<JavaChar>> = jvm.invoke_virtual(&s, "java/lang/String", "toCharArray", "()[C", ()).await?;
let length = jvm.array_length(&chars).await?;
Expand All @@ -238,14 +274,20 @@ impl DataOutputStream {
let mut bytes = jvm.instantiate_array("B", data.len()).await?;
jvm.store_array(&mut bytes, 0, data).await?;

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
jvm.invoke_virtual(&out, "java/io/OutputStream", "write", "([B)V", (bytes,)).await
}

async fn close(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
tracing::debug!("java.io.DataOutputStream::close({this:?})");

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
let _: () = jvm.invoke_virtual(&out, "java/io/OutputStream", "close", "()V", []).await?;

Ok(())
Expand All @@ -254,7 +296,10 @@ impl DataOutputStream {
async fn flush(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
tracing::debug!("java.io.DataOutputStream::flush({this:?})");

let out = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
let out: ClassInstanceRef<OutputStream> = jvm.get_field(&this, "java/io/DataOutputStream", "out", "Ljava/io/OutputStream;").await?;
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "underlying stream is null").await);
}
let _: () = jvm.invoke_virtual(&out, "java/io/OutputStream", "flush", "()V", []).await?;

Ok(())
Expand Down
3 changes: 3 additions & 0 deletions rustjava-runtime/src/classes/java/io/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ impl File {

async fn init(jvm: &Jvm, _: &mut RuntimeContext, mut this: ClassInstanceRef<Self>, pathname: ClassInstanceRef<String>) -> Result<()> {
tracing::debug!("java.io.File::<init>({this:?}, {pathname:?})");
if pathname.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let _: () = jvm.invoke_special(&this, "java/lang/Object", "<init>", "()V", ()).await?;

Expand Down
34 changes: 7 additions & 27 deletions rustjava-runtime/src/classes/java/io/file_descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,33 +32,13 @@ impl FileDescriptor {
async fn cl_init(jvm: &Jvm, runtime: &mut RuntimeContext) -> Result<()> {
tracing::debug!("java.io.FileDescriptor::<clinit>()");

let stderr_fd = runtime.stderr();
if let Ok(stderr_fd) = stderr_fd {
let mut stderr = jvm.new_class("java/io/FileDescriptor", "()V", []).await?;
jvm.put_field(&mut stderr, "java/io/FileDescriptor", "fd", "I", stderr_fd.id() as i32)
.await?;

jvm.put_static_field("java/io/FileDescriptor", "err", "Ljava/io/FileDescriptor;", stderr)
.await?;
}

let stdin_fd = runtime.stdin();
if let Ok(stdin_fd) = stdin_fd {
let mut stdin = jvm.new_class("java/io/FileDescriptor", "()V", []).await?;
jvm.put_field(&mut stdin, "java/io/FileDescriptor", "fd", "I", stdin_fd.id() as i32)
.await?;

jvm.put_static_field("java/io/FileDescriptor", "in", "Ljava/io/FileDescriptor;", stdin)
.await?;
}

let stdout_fd = runtime.stdout();
if let Ok(stdout_fd) = stdout_fd {
let mut stdout = jvm.new_class("java/io/FileDescriptor", "()V", []).await?;
jvm.put_field(&mut stdout, "java/io/FileDescriptor", "fd", "I", stdout_fd.id() as i32)
.await?;

jvm.put_static_field("java/io/FileDescriptor", "out", "Ljava/io/FileDescriptor;", stdout)
for (name, host_descriptor) in [("err", runtime.stderr()), ("in", runtime.stdin()), ("out", runtime.stdout())] {
let mut descriptor = jvm.new_class("java/io/FileDescriptor", "()V", []).await?;
if let Ok(host_descriptor) = host_descriptor {
jvm.put_field(&mut descriptor, "java/io/FileDescriptor", "fd", "I", host_descriptor.id() as i32)
.await?;
}
jvm.put_static_field("java/io/FileDescriptor", name, "Ljava/io/FileDescriptor;", descriptor)
.await?;
}

Expand Down
9 changes: 9 additions & 0 deletions rustjava-runtime/src/classes/java/io/file_input_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ impl FileInputStream {

async fn init(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>, file: ClassInstanceRef<File>) -> Result<()> {
tracing::debug!("java.io.FileInputStream::<init>({this:?}, {file:?})");
if file.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let path = jvm.invoke_virtual(&file, "java/io/File", "getPath", "()Ljava/lang/String;", ()).await?;
let path = JavaLangString::to_rust_string(jvm, &path).await?;
Expand Down Expand Up @@ -77,6 +80,9 @@ impl FileInputStream {
fd: ClassInstanceRef<FileDescriptor>,
) -> Result<()> {
tracing::debug!("java.io.FileInputStream::<init>({this:?}, {fd:?})");
if fd.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let _: () = jvm.invoke_special(&this, "java/io/InputStream", "<init>", "()V", ()).await?;

Expand Down Expand Up @@ -114,6 +120,9 @@ impl FileInputStream {
length: i32,
) -> Result<i32> {
tracing::debug!("java.io.FileInputStream::read({this:?}, {buf:?}, {offset:?}, {length:?})");
if buf.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let fd = jvm.get_field(&this, "java/io/FileInputStream", "fd", "Ljava/io/FileDescriptor;").await?;
let mut rust_file = FileDescriptor::file(jvm, context, fd).await?;
Expand Down
9 changes: 9 additions & 0 deletions rustjava-runtime/src/classes/java/io/file_output_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ impl FileOutputStream {
append: bool,
) -> Result<()> {
tracing::debug!("java.io.FileOutputStream::<init>({this:?}, {file:?}, {append})");
if file.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let path = jvm.invoke_virtual(&file, "java/io/File", "getPath", "()Ljava/lang/String;", ()).await?;
let path = JavaLangString::to_rust_string(jvm, &path).await?;
Expand Down Expand Up @@ -89,6 +92,9 @@ impl FileOutputStream {
file_descriptor: ClassInstanceRef<FileDescriptor>,
) -> Result<()> {
tracing::debug!("java.io.FileOutputStream::<init>({this:?}, {file_descriptor:?})");
if file_descriptor.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let _: () = jvm.invoke_special(&this, "java/io/OutputStream", "<init>", "()V", ()).await?;

Expand All @@ -108,6 +114,9 @@ impl FileOutputStream {
length: i32,
) -> Result<()> {
tracing::debug!("java.io.FileOutputStream::write({this:?}, {buffer:?}, {offset:?}, {length:?})");
if buffer.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "argument is null").await);
}

let fd = jvm.get_field(&this, "java/io/FileOutputStream", "fd", "Ljava/io/FileDescriptor;").await?;
let mut file = FileDescriptor::file(jvm, context, fd).await?;
Expand Down
Loading
Loading