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
52 changes: 20 additions & 32 deletions rustjava-runtime/src/classes/java/util/hash_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,18 +125,6 @@ impl HashMap {
Ok(entry_set.into())
}

async fn keys_snapshot(jvm: &Jvm, this: &ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Array<Object>>> {
Self::snapshot_entries(jvm, this, SnapshotKind::Keys).await
}

async fn values_snapshot(jvm: &Jvm, this: &ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Array<Object>>> {
Self::snapshot_entries(jvm, this, SnapshotKind::Values).await
}

async fn entries_snapshot(jvm: &Jvm, this: &ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Array<Object>>> {
Self::snapshot_entries(jvm, this, SnapshotKind::Entries).await
}

async fn init_with_capacity(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, capacity: i32) -> Result<()> {
tracing::debug!("java.util.HashMap::<init>({this:?}, {capacity:?})");

Expand Down Expand Up @@ -473,28 +461,40 @@ impl HashMap {
}

async fn key_iterator(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Object>> {
let snapshot = Self::keys_snapshot(jvm, &this).await?;
let snapshot = Self::snapshot_entries(jvm, &this).await?;

Ok(jvm
.new_class("java/util/HashMap$KeyIterator", "([Ljava/lang/Object;)V", (snapshot,))
.new_class(
"java/util/HashMap$KeyIterator",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
(this, snapshot),
)
.await?
.into())
}

async fn value_iterator(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Object>> {
let snapshot = Self::values_snapshot(jvm, &this).await?;
let snapshot = Self::snapshot_entries(jvm, &this).await?;

Ok(jvm
.new_class("java/util/HashMap$ValueIterator", "([Ljava/lang/Object;)V", (snapshot,))
.new_class(
"java/util/HashMap$ValueIterator",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
(this, snapshot),
)
.await?
.into())
}

async fn entry_iterator(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Object>> {
let snapshot = Self::entries_snapshot(jvm, &this).await?;
let snapshot = Self::snapshot_entries(jvm, &this).await?;

Ok(jvm
.new_class("java/util/HashMap$EntryIterator", "([Ljava/lang/Object;)V", (snapshot,))
.new_class(
"java/util/HashMap$EntryIterator",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
(this, snapshot),
)
.await?
.into())
}
Expand Down Expand Up @@ -655,7 +655,7 @@ impl HashMap {
(hash & 0x7FFFFFFF) as usize % table_len
}

async fn snapshot_entries(jvm: &Jvm, this: &ClassInstanceRef<Self>, kind: SnapshotKind) -> Result<ClassInstanceRef<Array<Object>>> {
async fn snapshot_entries(jvm: &Jvm, this: &ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Array<Object>>> {
let table: ClassInstanceRef<Array<HashMapEntry>> = jvm.get_field(this, "java/util/HashMap", "table", "[Ljava/util/HashMap$Entry;").await?;
let table_len = jvm.array_length(&table).await?;
let size: i32 = jvm.get_field(this, "java/util/HashMap", "size", "I").await?;
Expand All @@ -664,12 +664,7 @@ impl HashMap {
for bucket_index in 0..table_len {
let mut entry = Self::load_bucket(jvm, &table, bucket_index).await?;
while !entry.is_null() {
let element = match kind {
SnapshotKind::Keys => jvm.get_field(&entry, "java/util/HashMap$Entry", "key", "Ljava/lang/Object;").await?,
SnapshotKind::Values => jvm.get_field(&entry, "java/util/HashMap$Entry", "value", "Ljava/lang/Object;").await?,
SnapshotKind::Entries => ClassInstanceRef::new(entry.clone().instance),
};
elements.push(element);
elements.push(ClassInstanceRef::new(entry.clone().instance));

entry = jvm
.get_field(&entry, "java/util/HashMap$Entry", "next", "Ljava/util/HashMap$Entry;")
Expand All @@ -689,10 +684,3 @@ impl HashMap {
if capacity <= 0 { 0 } else { (capacity as f32 * load_factor) as i32 }
}
}

#[derive(Copy, Clone)]
enum SnapshotKind {
Keys,
Values,
Entries,
}
22 changes: 18 additions & 4 deletions rustjava-runtime/src/classes/java/util/hash_map_entry_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use jvm_types::{ClassAccessFlags, MethodAccessFlags};

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

use super::HashMap;

// class java.util.HashMap$EntryIterator
pub struct HashMapEntryIterator;

Expand All @@ -17,7 +19,7 @@ impl HashMapEntryIterator {
interfaces: vec![],
methods: vec![JavaMethodProto::new(
"<init>",
"([Ljava/lang/Object;)V",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
Self::init,
MethodAccessFlags::empty(),
)],
Expand All @@ -26,10 +28,22 @@ impl HashMapEntryIterator {
}
}

async fn init(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, elements: ClassInstanceRef<Array<Object>>) -> Result<()> {
async fn init(
jvm: &Jvm,
_: &mut RuntimeContext,
this: ClassInstanceRef<Self>,
map: ClassInstanceRef<HashMap>,
elements: ClassInstanceRef<Array<Object>>,
) -> Result<()> {
tracing::debug!("java.util.HashMap$EntryIterator::<init>({this:?}, {elements:?})");

jvm.invoke_special(&this, "java/util/HashMap$HashIterator", "<init>", "([Ljava/lang/Object;)V", (elements,))
.await
jvm.invoke_special(
&this,
"java/util/HashMap$HashIterator",
"<init>",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
(map, elements),
)
.await
}
}
58 changes: 52 additions & 6 deletions rustjava-runtime/src/classes/java/util/hash_map_hash_iterator.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use alloc::vec;
use alloc::{vec, vec::Vec};

use jvm::{Array, ClassInstanceRef, Jvm, Result};
use jvm_class_proto::{JavaFieldProto, JavaMethodProto};
use jvm_types::{ClassAccessFlags, FieldAccessFlags, MethodAccessFlags};

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

use super::{HashMap, HashMapEntry};

// abstract class java.util.HashMap$HashIterator
pub struct HashMapHashIterator;

Expand All @@ -16,24 +18,39 @@ impl HashMapHashIterator {
parent_class: Some("java/lang/Object"),
interfaces: vec!["java/util/Iterator"],
methods: vec![
JavaMethodProto::new("<init>", "([Ljava/lang/Object;)V", Self::init, MethodAccessFlags::empty()),
JavaMethodProto::new(
"<init>",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
Self::init,
MethodAccessFlags::empty(),
),
JavaMethodProto::new("hasNext", "()Z", Self::has_next, MethodAccessFlags::PUBLIC | MethodAccessFlags::FINAL),
JavaMethodProto::new("next", "()Ljava/lang/Object;", Self::next, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("remove", "()V", Self::remove, MethodAccessFlags::PUBLIC | MethodAccessFlags::FINAL),
],
fields: vec![
JavaFieldProto::new("map", "Ljava/util/HashMap;", FieldAccessFlags::PRIVATE),
JavaFieldProto::new("lastReturned", "Ljava/util/HashMap$Entry;", FieldAccessFlags::PRIVATE),
JavaFieldProto::new("elements", "[Ljava/lang/Object;", FieldAccessFlags::PRIVATE),
JavaFieldProto::new("index", "I", FieldAccessFlags::empty()),
],
access_flags: ClassAccessFlags::ABSTRACT,
}
}

async fn init(jvm: &Jvm, _: &mut RuntimeContext, mut this: ClassInstanceRef<Self>, elements: ClassInstanceRef<Array<Object>>) -> Result<()> {
async fn init(
jvm: &Jvm,
_: &mut RuntimeContext,
mut this: ClassInstanceRef<Self>,
map: ClassInstanceRef<HashMap>,
elements: ClassInstanceRef<Array<Object>>,
) -> Result<()> {
tracing::debug!("java.util.HashMap$HashIterator::<init>({this:?}, {elements:?})");

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

jvm.put_field(&mut this, "java/util/HashMap$HashIterator", "map", "Ljava/util/HashMap;", map)
.await?;
jvm.put_field(&mut this, "java/util/HashMap$HashIterator", "elements", "[Ljava/lang/Object;", elements)
.await?;
jvm.put_field(&mut this, "java/util/HashMap$HashIterator", "index", "I", 0).await?;
Expand Down Expand Up @@ -66,19 +83,48 @@ impl HashMapHashIterator {
return Err(jvm.exception("java/util/NoSuchElementException", "HashMap iterator exhausted").await);
}

let mut values = jvm.load_array(&elements, index as usize, 1).await?;
let mut values: Vec<ClassInstanceRef<Object>> = jvm.load_array(&elements, index as usize, 1).await?;
let Some(element) = values.pop() else {
return Err(jvm.exception("java/util/NoSuchElementException", "HashMap iterator exhausted").await);
};
jvm.put_field(&mut this, "java/util/HashMap$HashIterator", "index", "I", index + 1)
.await?;
jvm.put_field(
&mut this,
"java/util/HashMap$HashIterator",
"lastReturned",
"Ljava/util/HashMap$Entry;",
element.clone(),
)
.await?;

Ok(element)
}

async fn remove(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
async fn remove(jvm: &Jvm, _: &mut RuntimeContext, mut this: ClassInstanceRef<Self>) -> Result<()> {
tracing::debug!("java.util.HashMap$HashIterator::remove({this:?})");

Err(jvm.exception("java/lang/UnsupportedOperationException", "Iterator.remove").await)
let entry: ClassInstanceRef<HashMapEntry> = jvm
.get_field(&this, "java/util/HashMap$HashIterator", "lastReturned", "Ljava/util/HashMap$Entry;")
.await?;
if entry.is_null() {
return Err(jvm.exception("java/lang/IllegalStateException", "No entry to remove").await);
}
let map = jvm
.get_field(&this, "java/util/HashMap$HashIterator", "map", "Ljava/util/HashMap;")
.await?;
let key: ClassInstanceRef<Object> = jvm.get_field(&entry, "java/util/HashMap$Entry", "key", "Ljava/lang/Object;").await?;
let _: ClassInstanceRef<Object> = jvm
.invoke_virtual(&map, "java/util/HashMap", "remove", "(Ljava/lang/Object;)Ljava/lang/Object;", (key,))
.await?;
Comment thread
dlunch marked this conversation as resolved.
let null_entry: ClassInstanceRef<HashMapEntry> = None.into();
jvm.put_field(
&mut this,
"java/util/HashMap$HashIterator",
"lastReturned",
"Ljava/util/HashMap$Entry;",
null_entry,
)
.await
}
}
42 changes: 33 additions & 9 deletions rustjava-runtime/src/classes/java/util/hash_map_key_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use jvm_types::{ClassAccessFlags, MethodAccessFlags};

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

use super::HashMap;

// class java.util.HashMap$KeyIterator
pub struct HashMapKeyIterator;

Expand All @@ -15,21 +17,43 @@ impl HashMapKeyIterator {
name: "java/util/HashMap$KeyIterator",
parent_class: Some("java/util/HashMap$HashIterator"),
interfaces: vec![],
methods: vec![JavaMethodProto::new(
"<init>",
"([Ljava/lang/Object;)V",
Self::init,
MethodAccessFlags::empty(),
)],
methods: vec![
JavaMethodProto::new(
"<init>",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
Self::init,
MethodAccessFlags::empty(),
),
JavaMethodProto::new("next", "()Ljava/lang/Object;", Self::next, MethodAccessFlags::PUBLIC),
],
fields: vec![],
access_flags: ClassAccessFlags::FINAL,
}
}

async fn init(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, elements: ClassInstanceRef<Array<Object>>) -> Result<()> {
async fn next(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Object>> {
let entry = jvm
.invoke_special(&this, "java/util/HashMap$HashIterator", "next", "()Ljava/lang/Object;", ())
.await?;
jvm.get_field(&entry, "java/util/HashMap$Entry", "key", "Ljava/lang/Object;").await
}

async fn init(
jvm: &Jvm,
_: &mut RuntimeContext,
this: ClassInstanceRef<Self>,
map: ClassInstanceRef<HashMap>,
elements: ClassInstanceRef<Array<Object>>,
) -> Result<()> {
tracing::debug!("java.util.HashMap$KeyIterator::<init>({this:?}, {elements:?})");

jvm.invoke_special(&this, "java/util/HashMap$HashIterator", "<init>", "([Ljava/lang/Object;)V", (elements,))
.await
jvm.invoke_special(
&this,
"java/util/HashMap$HashIterator",
"<init>",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
(map, elements),
)
.await
}
}
42 changes: 33 additions & 9 deletions rustjava-runtime/src/classes/java/util/hash_map_value_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use jvm_types::{ClassAccessFlags, MethodAccessFlags};

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

use super::HashMap;

// class java.util.HashMap$ValueIterator
pub struct HashMapValueIterator;

Expand All @@ -15,21 +17,43 @@ impl HashMapValueIterator {
name: "java/util/HashMap$ValueIterator",
parent_class: Some("java/util/HashMap$HashIterator"),
interfaces: vec![],
methods: vec![JavaMethodProto::new(
"<init>",
"([Ljava/lang/Object;)V",
Self::init,
MethodAccessFlags::empty(),
)],
methods: vec![
JavaMethodProto::new(
"<init>",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
Self::init,
MethodAccessFlags::empty(),
),
JavaMethodProto::new("next", "()Ljava/lang/Object;", Self::next, MethodAccessFlags::PUBLIC),
],
fields: vec![],
access_flags: ClassAccessFlags::FINAL,
}
}

async fn init(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, elements: ClassInstanceRef<Array<Object>>) -> Result<()> {
async fn next(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Object>> {
let entry = jvm
.invoke_special(&this, "java/util/HashMap$HashIterator", "next", "()Ljava/lang/Object;", ())
.await?;
jvm.get_field(&entry, "java/util/HashMap$Entry", "value", "Ljava/lang/Object;").await
}

async fn init(
jvm: &Jvm,
_: &mut RuntimeContext,
this: ClassInstanceRef<Self>,
map: ClassInstanceRef<HashMap>,
elements: ClassInstanceRef<Array<Object>>,
) -> Result<()> {
tracing::debug!("java.util.HashMap$ValueIterator::<init>({this:?}, {elements:?})");

jvm.invoke_special(&this, "java/util/HashMap$HashIterator", "<init>", "([Ljava/lang/Object;)V", (elements,))
.await
jvm.invoke_special(
&this,
"java/util/HashMap$HashIterator",
"<init>",
"(Ljava/util/HashMap;[Ljava/lang/Object;)V",
(map, elements),
)
.await
}
}
6 changes: 5 additions & 1 deletion rustjava-runtime/src/classes/java/util/jar.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
mod attributes;
mod attributes_name;
mod jar_entry;
mod jar_file;
mod jar_file_entries;
mod manifest;

pub use {attributes::Attributes, jar_entry::JarEntry, jar_file::JarFile, jar_file_entries::JarFileEntries, manifest::Manifest};
pub use {
attributes::Attributes, attributes_name::AttributesName, jar_entry::JarEntry, jar_file::JarFile, jar_file_entries::JarFileEntries,
manifest::Manifest,
};
Loading
Loading