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
1 change: 1 addition & 0 deletions java_runtime/src/classes/java.rs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
pub mod io;
pub mod lang;
pub mod net;
pub mod text;
pub mod util;
13 changes: 13 additions & 0 deletions java_runtime/src/classes/java/text.rs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
mod date_format;
mod decimal_format;
mod field_position;
mod format;
mod number_format;
mod parse_exception;
mod parse_position;
mod simple_date_format;

pub use self::{
date_format::DateFormat, decimal_format::DecimalFormat, field_position::FieldPosition, format::Format, number_format::NumberFormat,
parse_exception::ParseException, parse_position::ParsePosition, simple_date_format::SimpleDateFormat,
};
580 changes: 580 additions & 0 deletions java_runtime/src/classes/java/text/date_format.rs

Large diffs are not rendered by default.

562 changes: 562 additions & 0 deletions java_runtime/src/classes/java/text/decimal_format.rs

Large diffs are not rendered by default.

101 changes: 101 additions & 0 deletions java_runtime/src/classes/java/text/field_position.rs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
use alloc::{format, vec};

use java_class_proto::{JavaFieldProto, JavaMethodProto};
use java_constants::{ClassAccessFlags, FieldAccessFlags, MethodAccessFlags};
use jvm::{ClassInstanceRef, Jvm, Result, runtime::JavaLangString};

use crate::{
RuntimeClassProto, RuntimeContext,
classes::java::lang::{Object, String},
};

// public class java.text.FieldPosition
pub struct FieldPosition;

impl FieldPosition {
pub fn as_proto() -> RuntimeClassProto {
RuntimeClassProto {
name: "java/text/FieldPosition",
parent_class: Some("java/lang/Object"),
interfaces: vec![],
methods: vec![
JavaMethodProto::new("<init>", "(I)V", Self::init, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("getField", "()I", Self::get_field, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("getBeginIndex", "()I", Self::get_begin_index, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("getEndIndex", "()I", Self::get_end_index, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("setBeginIndex", "(I)V", Self::set_begin_index, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("setEndIndex", "(I)V", Self::set_end_index, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("equals", "(Ljava/lang/Object;)Z", Self::equals, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("hashCode", "()I", Self::hash_code, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("toString", "()Ljava/lang/String;", Self::to_string, MethodAccessFlags::PUBLIC),
],
fields: vec![
JavaFieldProto::new("field", "I", FieldAccessFlags::PRIVATE),
JavaFieldProto::new("beginIndex", "I", FieldAccessFlags::PRIVATE),
JavaFieldProto::new("endIndex", "I", FieldAccessFlags::PRIVATE),
],
access_flags: ClassAccessFlags::PUBLIC,
}
}

async fn init(jvm: &Jvm, _: &mut RuntimeContext, mut this: ClassInstanceRef<Self>, field: i32) -> Result<()> {
let _: () = jvm.invoke_special(&this, "java/lang/Object", "<init>", "()V", ()).await?;
jvm.put_field(&mut this, "field", "I", field).await?;
jvm.put_field(&mut this, "beginIndex", "I", 0).await?;
jvm.put_field(&mut this, "endIndex", "I", 0).await
}

async fn get_field(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i32> {
jvm.get_field(&this, "field", "I").await
}

async fn get_begin_index(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i32> {
jvm.get_field(&this, "beginIndex", "I").await
}

async fn get_end_index(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i32> {
jvm.get_field(&this, "endIndex", "I").await
}

async fn set_begin_index(jvm: &Jvm, _: &mut RuntimeContext, mut this: ClassInstanceRef<Self>, value: i32) -> Result<()> {
jvm.put_field(&mut this, "beginIndex", "I", value).await
}

async fn set_end_index(jvm: &Jvm, _: &mut RuntimeContext, mut this: ClassInstanceRef<Self>, value: i32) -> Result<()> {
jvm.put_field(&mut this, "endIndex", "I", value).await
}

async fn equals(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, other: ClassInstanceRef<Object>) -> Result<bool> {
if other.is_null() || !jvm.is_instance(&**other, "java/text/FieldPosition") {
return Ok(false);
}

let other: ClassInstanceRef<Self> = ClassInstanceRef::new(other.instance);
let field: i32 = jvm.get_field(&this, "field", "I").await?;
let other_field: i32 = jvm.get_field(&other, "field", "I").await?;
let begin_index: i32 = jvm.get_field(&this, "beginIndex", "I").await?;
let other_begin_index: i32 = jvm.get_field(&other, "beginIndex", "I").await?;
let end_index: i32 = jvm.get_field(&this, "endIndex", "I").await?;
let other_end_index: i32 = jvm.get_field(&other, "endIndex", "I").await?;
Ok(field == other_field && begin_index == other_begin_index && end_index == other_end_index)
}

async fn hash_code(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i32> {
let field: i32 = jvm.get_field(&this, "field", "I").await?;
let begin_index: i32 = jvm.get_field(&this, "beginIndex", "I").await?;
let end_index: i32 = jvm.get_field(&this, "endIndex", "I").await?;
Ok(field ^ begin_index.rotate_left(11) ^ end_index.rotate_left(22))
}

async fn to_string(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<ClassInstanceRef<String>> {
let field: i32 = jvm.get_field(&this, "field", "I").await?;
let begin_index: i32 = jvm.get_field(&this, "beginIndex", "I").await?;
let end_index: i32 = jvm.get_field(&this, "endIndex", "I").await?;
Ok(JavaLangString::from_rust_string(
jvm,
&format!("java.text.FieldPosition[field={field},beginIndex={begin_index},endIndex={end_index}]"),
)
.await?
.into())
}
}
113 changes: 113 additions & 0 deletions java_runtime/src/classes/java/text/format.rs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
use alloc::vec;

use java_class_proto::JavaMethodProto;
use java_constants::{ClassAccessFlags, MethodAccessFlags};
use jvm::{ClassInstanceRef, JavaError, Jvm, Result, runtime::JavaLangString};

use crate::{
RuntimeClassProto, RuntimeContext,
classes::java::{
lang::{Object, String, StringBuffer},
text::{FieldPosition, ParseException, ParsePosition},
},
};

// public abstract class java.text.Format
pub struct Format;

impl Format {
pub fn as_proto() -> RuntimeClassProto {
RuntimeClassProto {
name: "java/text/Format",
parent_class: Some("java/lang/Object"),
interfaces: vec!["java/io/Serializable", "java/lang/Cloneable"],
methods: vec![
JavaMethodProto::new("<init>", "()V", Self::init, MethodAccessFlags::PROTECTED),
JavaMethodProto::new(
"format",
"(Ljava/lang/Object;)Ljava/lang/String;",
Self::format,
MethodAccessFlags::PUBLIC | MethodAccessFlags::FINAL,
),
JavaMethodProto::new_abstract(
"format",
"(Ljava/lang/Object;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;",
MethodAccessFlags::PUBLIC | MethodAccessFlags::ABSTRACT,
),
JavaMethodProto::new(
"parseObject",
"(Ljava/lang/String;)Ljava/lang/Object;",
Self::parse_object,
MethodAccessFlags::PUBLIC,
),
JavaMethodProto::new_abstract(
"parseObject",
"(Ljava/lang/String;Ljava/text/ParsePosition;)Ljava/lang/Object;",
MethodAccessFlags::PUBLIC | MethodAccessFlags::ABSTRACT,
),
JavaMethodProto::new("clone", "()Ljava/lang/Object;", Self::clone, MethodAccessFlags::PUBLIC),
],
fields: vec![],
access_flags: ClassAccessFlags::PUBLIC | ClassAccessFlags::ABSTRACT,
}
}

async fn init(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
jvm.invoke_special(&this, "java/lang/Object", "<init>", "()V", ()).await
}

async fn format(
jvm: &Jvm,
_: &mut RuntimeContext,
this: ClassInstanceRef<Self>,
object: ClassInstanceRef<Object>,
) -> Result<ClassInstanceRef<String>> {
let buffer: ClassInstanceRef<StringBuffer> = jvm.new_class("java/lang/StringBuffer", "()V", ()).await?.into();
let position: ClassInstanceRef<FieldPosition> = jvm.new_class("java/text/FieldPosition", "(I)V", (0,)).await?.into();
let buffer: ClassInstanceRef<StringBuffer> = jvm
.invoke_virtual(
&this,
"format",
"(Ljava/lang/Object;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;",
(object, buffer, position),
)
.await?;
jvm.invoke_virtual(&buffer, "toString", "()Ljava/lang/String;", ()).await
}

async fn parse_object(
jvm: &Jvm,
_: &mut RuntimeContext,
this: ClassInstanceRef<Self>,
source: ClassInstanceRef<String>,
) -> Result<ClassInstanceRef<Object>> {
if source.is_null() {
return Err(jvm.exception("java/lang/NullPointerException", "source").await);
}

let position: ClassInstanceRef<ParsePosition> = jvm.new_class("java/text/ParsePosition", "(I)V", (0,)).await?.into();
let result: ClassInstanceRef<Object> = jvm
.invoke_virtual(
&this,
"parseObject",
"(Ljava/lang/String;Ljava/text/ParsePosition;)Ljava/lang/Object;",
(source, position.clone()),
)
.await?;
let index: i32 = jvm.invoke_virtual(&position, "getIndex", "()I", ()).await?;
if index == 0 {
let error_index: i32 = jvm.invoke_virtual(&position, "getErrorIndex", "()I", ()).await?;
let message = JavaLangString::from_rust_string(jvm, "Format.parseObject(String) failed").await?;
let exception: ClassInstanceRef<ParseException> = jvm
.new_class("java/text/ParseException", "(Ljava/lang/String;I)V", (message, error_index))
.await?
.into();
return Err(JavaError::JavaException(exception.into()));
}
Ok(result)
}

async fn clone(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Object>> {
Ok(jvm.shallow_clone(&this)?.into())
}
}
Loading