11use alloc:: vec;
22
3- use java_class_proto:: JavaMethodProto ;
3+ use java_class_proto:: { JavaFieldProto , JavaMethodProto } ;
44use jvm:: { ClassInstanceRef , Jvm , Result } ;
55
66use 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