Skip to content

Commit 146b887

Browse files
committed
add java 1.2 collections framework
1 parent 798393a commit 146b887

46 files changed

Lines changed: 5073 additions & 52 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

java_runtime/src/classes/java/util.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,59 @@ pub mod zip;
33

44
mod abstract_collection;
55
mod abstract_list;
6+
mod abstract_map;
7+
mod abstract_set;
8+
mod array_list;
9+
mod array_list_itr;
610
mod calendar;
11+
mod collection;
712
mod date;
813
mod dictionary;
914
mod empty_stack_exception;
1015
mod enumeration;
1116
mod gregorian_calendar;
17+
mod hash_map;
18+
mod hash_map_entry;
19+
mod hash_map_entry_iterator;
20+
mod hash_map_entry_set;
21+
mod hash_map_hash_iterator;
22+
mod hash_map_key_iterator;
23+
mod hash_map_key_set;
24+
mod hash_map_value_iterator;
25+
mod hash_map_values;
26+
mod hash_set;
1227
mod hashtable;
1328
mod hashtable_entry;
29+
mod hashtable_entry_set;
30+
mod hashtable_enumerator;
31+
mod hashtable_key_set;
32+
mod hashtable_values;
33+
mod iterator;
34+
mod list;
35+
mod map;
36+
mod map_entry;
1437
mod no_such_element_exception;
1538
mod properties;
1639
mod random;
40+
mod set;
1741
mod simple_time_zone;
1842
mod stack;
1943
mod time_zone;
2044
mod timer;
2145
mod timer_task;
2246
mod timer_thread;
2347
mod vector;
48+
mod vector_itr;
2449

2550
pub use self::{
26-
abstract_collection::AbstractCollection, abstract_list::AbstractList, calendar::Calendar, date::Date, dictionary::Dictionary,
27-
empty_stack_exception::EmptyStackException, enumeration::Enumeration, gregorian_calendar::GregorianCalendar, hashtable::Hashtable,
28-
hashtable_entry::HashtableEntry, no_such_element_exception::NoSuchElementException, properties::Properties, random::Random,
29-
simple_time_zone::SimpleTimeZone, stack::Stack, time_zone::TimeZone, timer::Timer, timer_task::TimerTask, timer_thread::TimerThread,
30-
vector::Vector,
51+
abstract_collection::AbstractCollection, abstract_list::AbstractList, abstract_map::AbstractMap, abstract_set::AbstractSet,
52+
array_list::ArrayList, array_list_itr::ArrayListItr, calendar::Calendar, collection::Collection, date::Date, dictionary::Dictionary,
53+
empty_stack_exception::EmptyStackException, enumeration::Enumeration, gregorian_calendar::GregorianCalendar, hash_map::HashMap,
54+
hash_map_entry::HashMapEntry, hash_map_entry_iterator::HashMapEntryIterator, hash_map_entry_set::HashMapEntrySet,
55+
hash_map_hash_iterator::HashMapHashIterator, hash_map_key_iterator::HashMapKeyIterator, hash_map_key_set::HashMapKeySet,
56+
hash_map_value_iterator::HashMapValueIterator, hash_map_values::HashMapValues, hash_set::HashSet, hashtable::Hashtable,
57+
hashtable_entry::HashtableEntry, hashtable_entry_set::HashtableEntrySet, hashtable_enumerator::HashtableEnumerator,
58+
hashtable_key_set::HashtableKeySet, hashtable_values::HashtableValues, iterator::Iterator, list::List, map::Map, map_entry::MapEntry,
59+
no_such_element_exception::NoSuchElementException, properties::Properties, random::Random, set::Set, simple_time_zone::SimpleTimeZone,
60+
stack::Stack, time_zone::TimeZone, timer::Timer, timer_task::TimerTask, timer_thread::TimerThread, vector::Vector, vector_itr::VectorItr,
3161
};

java_runtime/src/classes/java/util/abstract_collection.rs

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use alloc::vec;
22

33
use java_class_proto::JavaMethodProto;
44
use java_constants::ClassAccessFlags;
5-
use jvm::{ClassInstanceRef, Jvm, Result};
5+
use jvm::{Array, ClassInstanceRef, Jvm, Result};
66

7-
use crate::{RuntimeClassProto, RuntimeContext};
7+
use crate::{RuntimeClassProto, RuntimeContext, classes::java::lang::Object};
88

99
// abstract class java.util.AbstractCollection
1010
pub struct AbstractCollection;
@@ -14,8 +14,18 @@ impl AbstractCollection {
1414
RuntimeClassProto {
1515
name: "java/util/AbstractCollection",
1616
parent_class: Some("java/lang/Object"),
17-
interfaces: vec![],
18-
methods: vec![JavaMethodProto::new("<init>", "()V", Self::init, Default::default())],
17+
interfaces: vec!["java/util/Collection"],
18+
methods: vec![
19+
JavaMethodProto::new("<init>", "()V", Self::init, Default::default()),
20+
JavaMethodProto::new_abstract("size", "()I", Default::default()),
21+
JavaMethodProto::new("isEmpty", "()Z", Self::is_empty, Default::default()),
22+
JavaMethodProto::new("contains", "(Ljava/lang/Object;)Z", Self::contains, Default::default()),
23+
JavaMethodProto::new_abstract("iterator", "()Ljava/util/Iterator;", Default::default()),
24+
JavaMethodProto::new("toArray", "()[Ljava/lang/Object;", Self::to_array, Default::default()),
25+
JavaMethodProto::new("add", "(Ljava/lang/Object;)Z", Self::add, Default::default()),
26+
JavaMethodProto::new("remove", "(Ljava/lang/Object;)Z", Self::remove, Default::default()),
27+
JavaMethodProto::new("clear", "()V", Self::clear, Default::default()),
28+
],
1929
fields: vec![],
2030
access_flags: ClassAccessFlags::ABSTRACT,
2131
}
@@ -28,4 +38,84 @@ impl AbstractCollection {
2838

2939
Ok(())
3040
}
41+
42+
async fn is_empty(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<bool> {
43+
tracing::debug!("java.util.AbstractCollection::isEmpty({this:?})");
44+
45+
let size: i32 = jvm.invoke_virtual(&this, "size", "()I", ()).await?;
46+
47+
Ok(size == 0)
48+
}
49+
50+
async fn contains(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, element: ClassInstanceRef<Object>) -> Result<bool> {
51+
tracing::debug!("java.util.AbstractCollection::contains({this:?}, {element:?})");
52+
53+
let iterator: ClassInstanceRef<Object> = jvm.invoke_virtual(&this, "iterator", "()Ljava/util/Iterator;", ()).await?;
54+
loop {
55+
let has_next: bool = jvm.invoke_virtual(&iterator, "hasNext", "()Z", ()).await?;
56+
if !has_next {
57+
return Ok(false);
58+
}
59+
60+
let current: ClassInstanceRef<Object> = jvm.invoke_virtual(&iterator, "next", "()Ljava/lang/Object;", ()).await?;
61+
if Self::object_equals(jvm, &element, &current).await? {
62+
return Ok(true);
63+
}
64+
}
65+
}
66+
67+
async fn to_array(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Array<Object>>> {
68+
tracing::debug!("java.util.AbstractCollection::toArray({this:?})");
69+
70+
let iterator: ClassInstanceRef<Object> = jvm.invoke_virtual(&this, "iterator", "()Ljava/util/Iterator;", ()).await?;
71+
let mut elements = vec![];
72+
loop {
73+
let has_next: bool = jvm.invoke_virtual(&iterator, "hasNext", "()Z", ()).await?;
74+
if !has_next {
75+
break;
76+
}
77+
78+
let current: ClassInstanceRef<Object> = jvm.invoke_virtual(&iterator, "next", "()Ljava/lang/Object;", ()).await?;
79+
elements.push(current);
80+
}
81+
82+
let mut array: ClassInstanceRef<Array<Object>> = jvm.instantiate_array("Ljava/lang/Object;", elements.len()).await?.into();
83+
if !elements.is_empty() {
84+
jvm.store_array(&mut array, 0, elements).await?;
85+
}
86+
87+
Ok(array)
88+
}
89+
90+
async fn add(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, element: ClassInstanceRef<Object>) -> Result<bool> {
91+
tracing::debug!("java.util.AbstractCollection::add({this:?}, {element:?})");
92+
93+
Err(jvm.exception("java/lang/UnsupportedOperationException", "AbstractCollection.add").await)
94+
}
95+
96+
async fn remove(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, element: ClassInstanceRef<Object>) -> Result<bool> {
97+
tracing::debug!("java.util.AbstractCollection::remove({this:?}, {element:?})");
98+
99+
Err(jvm
100+
.exception("java/lang/UnsupportedOperationException", "AbstractCollection.remove")
101+
.await)
102+
}
103+
104+
async fn clear(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
105+
tracing::debug!("java.util.AbstractCollection::clear({this:?})");
106+
107+
Err(jvm.exception("java/lang/UnsupportedOperationException", "AbstractCollection.clear").await)
108+
}
109+
110+
async fn object_equals(jvm: &Jvm, left: &ClassInstanceRef<Object>, right: &ClassInstanceRef<Object>) -> Result<bool> {
111+
if left.is_null() {
112+
return Ok(right.is_null());
113+
}
114+
115+
if right.is_null() {
116+
return Ok(false);
117+
}
118+
119+
jvm.invoke_virtual(left, "equals", "(Ljava/lang/Object;)Z", (right.clone(),)).await
120+
}
31121
}

java_runtime/src/classes/java/util/abstract_list.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ impl AbstractList {
1414
RuntimeClassProto {
1515
name: "java/util/AbstractList",
1616
parent_class: Some("java/util/AbstractCollection"),
17-
interfaces: vec![],
17+
interfaces: vec!["java/util/List"],
1818
methods: vec![JavaMethodProto::new("<init>", "()V", Self::init, Default::default())],
1919
fields: vec![],
2020
access_flags: ClassAccessFlags::ABSTRACT,
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use alloc::vec;
2+
3+
use java_class_proto::JavaMethodProto;
4+
use java_constants::ClassAccessFlags;
5+
use jvm::{ClassInstanceRef, Jvm, Result};
6+
7+
use crate::{RuntimeClassProto, RuntimeContext};
8+
9+
// abstract class java.util.AbstractMap
10+
pub struct AbstractMap;
11+
12+
impl AbstractMap {
13+
pub fn as_proto() -> RuntimeClassProto {
14+
RuntimeClassProto {
15+
name: "java/util/AbstractMap",
16+
parent_class: Some("java/lang/Object"),
17+
interfaces: vec!["java/util/Map"],
18+
methods: vec![
19+
JavaMethodProto::new("<init>", "()V", Self::init, Default::default()),
20+
JavaMethodProto::new_abstract("size", "()I", Default::default()),
21+
JavaMethodProto::new("isEmpty", "()Z", Self::is_empty, Default::default()),
22+
],
23+
fields: vec![],
24+
access_flags: ClassAccessFlags::ABSTRACT,
25+
}
26+
}
27+
28+
async fn init(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
29+
tracing::debug!("java.util.AbstractMap::<init>({this:?})");
30+
31+
let _: () = jvm.invoke_special(&this, "java/lang/Object", "<init>", "()V", ()).await?;
32+
33+
Ok(())
34+
}
35+
36+
async fn is_empty(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<bool> {
37+
tracing::debug!("java.util.AbstractMap::isEmpty({this:?})");
38+
39+
let size: i32 = jvm.invoke_virtual(&this, "size", "()I", ()).await?;
40+
41+
Ok(size == 0)
42+
}
43+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use alloc::vec;
2+
3+
use java_class_proto::JavaMethodProto;
4+
use java_constants::ClassAccessFlags;
5+
use jvm::{ClassInstanceRef, Jvm, Result};
6+
7+
use crate::{RuntimeClassProto, RuntimeContext};
8+
9+
// abstract class java.util.AbstractSet
10+
pub struct AbstractSet;
11+
12+
impl AbstractSet {
13+
pub fn as_proto() -> RuntimeClassProto {
14+
RuntimeClassProto {
15+
name: "java/util/AbstractSet",
16+
parent_class: Some("java/util/AbstractCollection"),
17+
interfaces: vec!["java/util/Set"],
18+
methods: vec![JavaMethodProto::new("<init>", "()V", Self::init, Default::default())],
19+
fields: vec![],
20+
access_flags: ClassAccessFlags::ABSTRACT,
21+
}
22+
}
23+
24+
async fn init(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
25+
tracing::debug!("java.util.AbstractSet::<init>({this:?})");
26+
27+
let _: () = jvm.invoke_special(&this, "java/util/AbstractCollection", "<init>", "()V", ()).await?;
28+
29+
Ok(())
30+
}
31+
}

0 commit comments

Comments
 (0)