Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
17 changes: 10 additions & 7 deletions java_runtime/src/classes/java/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod byte_array_input_stream;
mod byte_array_output_stream;
mod char_array_reader;
mod char_array_writer;
mod closeable;
mod data_input;
mod data_input_stream;
mod data_output;
Expand All @@ -20,6 +21,7 @@ mod file_reader;
mod file_writer;
mod filter_input_stream;
mod filter_output_stream;
mod flushable;
mod input_stream;
mod input_stream_reader;
mod interrupted_io_exception;
Expand All @@ -40,12 +42,13 @@ mod writer;
pub use self::{
buffered_input_stream::BufferedInputStream, buffered_output_stream::BufferedOutputStream, buffered_reader::BufferedReader,
buffered_writer::BufferedWriter, byte_array_input_stream::ByteArrayInputStream, byte_array_output_stream::ByteArrayOutputStream,
char_array_reader::CharArrayReader, char_array_writer::CharArrayWriter, data_input::DataInput, data_input_stream::DataInputStream,
data_output::DataOutput, data_output_stream::DataOutputStream, eof_exception::EOFException, file::File, file_descriptor::FileDescriptor,
file_input_stream::FileInputStream, file_not_found_exception::FileNotFoundException, file_output_stream::FileOutputStream,
file_reader::FileReader, file_writer::FileWriter, filter_input_stream::FilterInputStream, filter_output_stream::FilterOutputStream,
input_stream::InputStream, input_stream_reader::InputStreamReader, interrupted_io_exception::InterruptedIOException, io_exception::IOException,
output_stream::OutputStream, output_stream_writer::OutputStreamWriter, print_stream::PrintStream, print_writer::PrintWriter,
random_access_file::RandomAccessFile, reader::Reader, serializable::Serializable, string_reader::StringReader, string_writer::StringWriter,
char_array_reader::CharArrayReader, char_array_writer::CharArrayWriter, closeable::Closeable, data_input::DataInput,
data_input_stream::DataInputStream, data_output::DataOutput, data_output_stream::DataOutputStream, eof_exception::EOFException, file::File,
file_descriptor::FileDescriptor, file_input_stream::FileInputStream, file_not_found_exception::FileNotFoundException,
file_output_stream::FileOutputStream, file_reader::FileReader, file_writer::FileWriter, filter_input_stream::FilterInputStream,
filter_output_stream::FilterOutputStream, flushable::Flushable, input_stream::InputStream, input_stream_reader::InputStreamReader,
interrupted_io_exception::InterruptedIOException, io_exception::IOException, output_stream::OutputStream,
output_stream_writer::OutputStreamWriter, print_stream::PrintStream, print_writer::PrintWriter, random_access_file::RandomAccessFile,
reader::Reader, serializable::Serializable, string_reader::StringReader, string_writer::StringWriter,
unsupported_encoding_exception::UnsupportedEncodingException, utf_data_format_exception::UTFDataFormatException, writer::Writer,
};
26 changes: 26 additions & 0 deletions java_runtime/src/classes/java/io/closeable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use alloc::vec;

use java_class_proto::JavaMethodProto;
use java_constants::{ClassAccessFlags, MethodAccessFlags};

use crate::RuntimeClassProto;

// public interface java.io.Closeable
pub struct Closeable;

impl Closeable {
pub fn as_proto() -> RuntimeClassProto {
RuntimeClassProto {
name: "java/io/Closeable",
parent_class: None,
interfaces: vec![],
methods: vec![JavaMethodProto::new_abstract(
"close",
"()V",
MethodAccessFlags::PUBLIC | MethodAccessFlags::ABSTRACT,
)],
fields: vec![],
access_flags: ClassAccessFlags::PUBLIC | ClassAccessFlags::INTERFACE | ClassAccessFlags::ABSTRACT,
}
}
}
26 changes: 26 additions & 0 deletions java_runtime/src/classes/java/io/flushable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use alloc::vec;

use java_class_proto::JavaMethodProto;
use java_constants::{ClassAccessFlags, MethodAccessFlags};

use crate::RuntimeClassProto;

// public interface java.io.Flushable
pub struct Flushable;

impl Flushable {
pub fn as_proto() -> RuntimeClassProto {
RuntimeClassProto {
name: "java/io/Flushable",
parent_class: None,
interfaces: vec![],
methods: vec![JavaMethodProto::new_abstract(
"flush",
"()V",
MethodAccessFlags::PUBLIC | MethodAccessFlags::ABSTRACT,
)],
fields: vec![],
access_flags: ClassAccessFlags::PUBLIC | ClassAccessFlags::INTERFACE | ClassAccessFlags::ABSTRACT,
}
}
}
18 changes: 9 additions & 9 deletions java_runtime/src/classes/java/io/output_stream.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloc::vec;

use java_class_proto::JavaMethodProto;
use java_constants::ClassAccessFlags;
use java_constants::{ClassAccessFlags, MethodAccessFlags};
use jvm::{Array, ClassInstanceRef, Jvm, Result};

use crate::{RuntimeClassProto, RuntimeContext};
Expand All @@ -14,17 +14,17 @@ impl OutputStream {
RuntimeClassProto {
name: "java/io/OutputStream",
parent_class: Some("java/lang/Object"),
interfaces: vec![],
interfaces: vec!["java/io/Closeable", "java/io/Flushable"],
methods: vec![
JavaMethodProto::new("<init>", "()V", Self::init, Default::default()),
JavaMethodProto::new("write", "([B)V", Self::write_bytes, Default::default()),
JavaMethodProto::new("write", "([BII)V", Self::write_bytes_offset, Default::default()),
JavaMethodProto::new_abstract("write", "(I)V", Default::default()),
JavaMethodProto::new("flush", "()V", Self::flush, Default::default()),
JavaMethodProto::new("close", "()V", Self::close, Default::default()),
JavaMethodProto::new("<init>", "()V", Self::init, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("write", "([B)V", Self::write_bytes, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("write", "([BII)V", Self::write_bytes_offset, MethodAccessFlags::PUBLIC),
JavaMethodProto::new_abstract("write", "(I)V", MethodAccessFlags::PUBLIC | MethodAccessFlags::ABSTRACT),
JavaMethodProto::new("flush", "()V", Self::flush, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("close", "()V", Self::close, MethodAccessFlags::PUBLIC),
],
fields: vec![],
access_flags: ClassAccessFlags::ABSTRACT,
access_flags: ClassAccessFlags::PUBLIC | ClassAccessFlags::ABSTRACT,
}
}

Expand Down
25 changes: 16 additions & 9 deletions java_runtime/src/classes/java/io/output_stream_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,30 @@ impl OutputStreamWriter {
) -> Result<()> {
tracing::debug!("java.io.OutputStreamWriter::<init>({this:?}, {out:?}, {encoding:?})");

if out.is_null() || encoding.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "output or encoding is null").await);
if out.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "output is null").await);
}
Self::validate_encoding(jvm, &encoding).await?;

let encoding_name = JavaLangString::to_rust_string(jvm, &encoding).await?.to_ascii_uppercase();
let _: () = jvm.invoke_special(&this, "java/io/Writer", "<init>", "()V", ()).await?;
jvm.put_field(&mut this, "out", "Ljava/io/OutputStream;", out).await?;
jvm.put_field(&mut this, "encoding", "Ljava/lang/String;", encoding).await?;
jvm.put_field(&mut this, "hasPendingHighSurrogate", "Z", false).await?;

Ok(())
}

pub(crate) async fn validate_encoding(jvm: &Jvm, encoding: &ClassInstanceRef<String>) -> Result<()> {
if encoding.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "encoding is null").await);
}
let encoding_name = JavaLangString::to_rust_string(jvm, encoding).await?.to_ascii_uppercase();
if !matches!(
encoding_name.as_str(),
"UTF-8" | "UTF8" | "EUC-KR" | "EUCKR" | "KS-C-5601-1987" | "MS949" | "CP949"
) {
return Err(jvm.exception("java/io/UnsupportedEncodingException", &encoding_name).await);
}

let _: () = jvm.invoke_special(&this, "java/io/Writer", "<init>", "()V", ()).await?;
jvm.put_field(&mut this, "out", "Ljava/io/OutputStream;", out).await?;
jvm.put_field(&mut this, "encoding", "Ljava/lang/String;", encoding).await?;
jvm.put_field(&mut this, "hasPendingHighSurrogate", "Z", false).await?;

Ok(())
}

Expand Down
Loading