Skip to content

Commit fdadcd7

Browse files
committed
Implement java random
1 parent 87a7734 commit fdadcd7

File tree

1 file changed

+48
-10
lines changed

1 file changed

+48
-10
lines changed

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

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use alloc::vec;
22

3-
use java_class_proto::JavaMethodProto;
3+
use java_class_proto::{JavaFieldProto, JavaMethodProto};
44
use jvm::{ClassInstanceRef, Jvm, Result};
55

66
use crate::{RuntimeClassProto, RuntimeContext};
@@ -19,27 +19,65 @@ impl Random {
1919
JavaMethodProto::new("<init>", "(J)V", Self::init_with_seed, Default::default()),
2020
JavaMethodProto::new("nextInt", "()I", Self::next_int, Default::default()),
2121
],
22-
fields: vec![],
22+
fields: vec![JavaFieldProto::new("seed", "J", Default::default())],
2323
}
2424
}
2525

26-
async fn init(_: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
27-
tracing::warn!("stub java.util.Random::<init>({:?})", &this);
26+
async fn init(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
27+
tracing::debug!("java.util.Random::<init>({:?})", &this);
28+
29+
let default_seed = 0i64; // TODO
30+
let _: () = jvm.invoke_special(&this, "java/util/Random", "<init>", "(J)V", (default_seed,)).await?;
2831

2932
Ok(())
3033
}
3134

32-
async fn init_with_seed(_: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, seed: i64) -> Result<()> {
33-
tracing::warn!("stub java.util.Random::<init>({:?}, {:?})", &this, seed);
35+
async fn init_with_seed(jvm: &Jvm, _: &mut RuntimeContext, mut this: ClassInstanceRef<Self>, seed: i64) -> Result<()> {
36+
tracing::debug!("java.util.Random::<init>({:?}, {:?})", &this, seed);
37+
38+
let _: () = jvm.invoke_special(&this, "java/lang/Object", "<init>", "()V", ()).await?;
39+
40+
// TODO constant
41+
let seed = (seed ^ 0x5DEECE66D) & ((1 << 48) - 1);
42+
43+
jvm.put_field(&mut this, "seed", "J", seed).await?;
3444

3545
Ok(())
3646
}
3747

38-
async fn next_int(_: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i32> {
39-
tracing::warn!("stub java.util.Random::nextInt({:?})", &this);
48+
async fn next_int(jvm: &Jvm, _: &mut RuntimeContext, mut this: ClassInstanceRef<Self>) -> Result<i32> {
49+
tracing::debug!("java.util.Random::nextInt({:?})", &this);
50+
51+
let seed: i64 = jvm.get_field(&this, "seed", "J").await?;
52+
let next_seed = seed.wrapping_mul(0x5DEECE66D).wrapping_add(0xB) & 0xFFFFFFFFFFFF;
53+
54+
jvm.put_field(&mut this, "seed", "J", next_seed).await?;
55+
56+
let value = next_seed.wrapping_shr(16) as i32;
57+
58+
Ok(value)
59+
}
60+
}
61+
62+
#[cfg(test)]
63+
mod test {
64+
use jvm::Result;
65+
66+
use crate::test::test_jvm;
4067

41-
let random = 12351352; // TODO
68+
#[tokio::test]
69+
async fn test_random() -> Result<()> {
70+
let jvm = test_jvm().await?;
4271

43-
Ok(random)
72+
let seed = 42i64;
73+
let random = jvm.new_class("java/util/Random", "(J)V", (seed,)).await?;
74+
75+
let next: i32 = jvm.invoke_virtual(&random, "nextInt", "()I", ()).await?;
76+
assert_eq!(next, -1170105035);
77+
78+
let next: i32 = jvm.invoke_virtual(&random, "nextInt", "()I", ()).await?;
79+
assert_eq!(next, 234785527);
80+
81+
Ok(())
4482
}
4583
}

0 commit comments

Comments
 (0)