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
1 change: 1 addition & 0 deletions java_runtime/src/classes/java.rs
Original file line number Diff line number Diff 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 number Diff line number Diff 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.

525 changes: 525 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 number Diff line number Diff 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 number Diff line number Diff 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