1- use alloc:: vec;
1+ use alloc:: { vec, vec :: Vec } ;
22
33use java_class_proto:: { JavaFieldProto , JavaMethodProto } ;
44use jvm:: { Array , ClassInstanceRef , Jvm , Result } ;
55
6- use crate :: { RuntimeClassProto , RuntimeContext } ;
6+ use crate :: { RuntimeClassProto , RuntimeContext , classes :: java :: lang :: String } ;
77
88// class java.io.ByteArrayOutputStream
99pub struct ByteArrayOutputStream ;
@@ -18,7 +18,9 @@ impl ByteArrayOutputStream {
1818 JavaMethodProto :: new( "<init>" , "()V" , Self :: init, Default :: default ( ) ) ,
1919 JavaMethodProto :: new( "<init>" , "(I)V" , Self :: init_with_size, Default :: default ( ) ) ,
2020 JavaMethodProto :: new( "write" , "(I)V" , Self :: write, Default :: default ( ) ) ,
21+ JavaMethodProto :: new( "write" , "([BII)V" , Self :: write_bytes, Default :: default ( ) ) ,
2122 JavaMethodProto :: new( "toByteArray" , "()[B" , Self :: to_byte_array, Default :: default ( ) ) ,
23+ JavaMethodProto :: new( "toString" , "()Ljava/lang/String;" , Self :: to_string, Default :: default ( ) ) ,
2224 JavaMethodProto :: new( "size" , "()I" , Self :: size, Default :: default ( ) ) ,
2325 JavaMethodProto :: new( "reset" , "()V" , Self :: reset, Default :: default ( ) ) ,
2426 JavaMethodProto :: new( "close" , "()V" , Self :: close, Default :: default ( ) ) ,
@@ -44,16 +46,43 @@ impl ByteArrayOutputStream {
4446 async fn init_with_size ( jvm : & Jvm , _: & mut RuntimeContext , mut this : ClassInstanceRef < Self > , size : i32 ) -> Result < ( ) > {
4547 tracing:: debug!( "java.io.ByteArrayOutputStream::<init>({this:?}, {size:?})" ) ;
4648
49+ if size < 0 {
50+ return Err ( jvm. exception ( "java/lang/IllegalArgumentException" , "Negative initial size" ) . await ) ;
51+ }
52+
4753 let _: ( ) = jvm. invoke_special ( & this, "java/io/OutputStream" , "<init>" , "()V" , ( ) ) . await ?;
4854
49- let array = jvm. instantiate_array ( "B" , 1024 ) . await ?;
55+ let array = jvm. instantiate_array ( "B" , size as usize ) . await ?;
5056
5157 jvm. put_field ( & mut this, "buf" , "[B" , array) . await ?;
5258 jvm. put_field ( & mut this, "pos" , "I" , 0 ) . await ?;
5359
5460 Ok ( ( ) )
5561 }
5662
63+ async fn write_bytes (
64+ jvm : & Jvm ,
65+ _: & mut RuntimeContext ,
66+ mut this : ClassInstanceRef < Self > ,
67+ bytes : ClassInstanceRef < Array < i8 > > ,
68+ off : i32 ,
69+ len : i32 ,
70+ ) -> Result < ( ) > {
71+ tracing:: debug!( "java.io.ByteArrayOutputStream::write({this:?}, {bytes:?}, {off}, {len})" ) ;
72+
73+ let length = jvm. array_length ( & bytes) . await ? as i32 ;
74+ if off < 0 || len < 0 || off > length - len {
75+ return Err ( jvm. exception ( "java/lang/IndexOutOfBoundsException" , "Invalid offset or length" ) . await ) ;
76+ }
77+
78+ let pos: i32 = jvm. get_field ( & this, "pos" , "I" ) . await ?;
79+ Self :: ensure_capacity ( jvm, & mut this, ( pos + len) as usize ) . await ?;
80+ let mut buf = jvm. get_field ( & this, "buf" , "[B" ) . await ?;
81+ let values: Vec < i8 > = jvm. load_array ( & bytes, off as usize , len as usize ) . await ?;
82+ jvm. store_array ( & mut buf, pos as usize , values) . await ?;
83+ jvm. put_field ( & mut this, "pos" , "I" , pos + len) . await
84+ }
85+
5786 async fn write ( jvm : & Jvm , _: & mut RuntimeContext , mut this : ClassInstanceRef < Self > , b : i32 ) -> Result < ( ) > {
5887 tracing:: debug!( "java.io.ByteArrayOutputStream::write({this:?}, {b:?})" ) ;
5988
@@ -95,6 +124,22 @@ impl ByteArrayOutputStream {
95124 Ok ( pos)
96125 }
97126
127+ async fn to_string ( jvm : & Jvm , _: & mut RuntimeContext , this : ClassInstanceRef < Self > ) -> Result < ClassInstanceRef < String > > {
128+ tracing:: debug!( "java.io.ByteArrayOutputStream::toString({this:?})" ) ;
129+ let buf: ClassInstanceRef < Array < i8 > > = jvm. get_field ( & this, "buf" , "[B" ) . await ?;
130+ let pos: i32 = jvm. get_field ( & this, "pos" , "I" ) . await ?;
131+ let bytes = jvm. instantiate_array ( "B" , pos as usize ) . await ?;
132+ let _: ( ) = jvm
133+ . invoke_static (
134+ "java/lang/System" ,
135+ "arraycopy" ,
136+ "(Ljava/lang/Object;ILjava/lang/Object;II)V" ,
137+ ( buf, 0 , bytes. clone ( ) , 0 , pos) ,
138+ )
139+ . await ?;
140+ Ok ( jvm. new_class ( "java/lang/String" , "([B)V" , ( bytes, ) ) . await ?. into ( ) )
141+ }
142+
98143 async fn reset ( jvm : & Jvm , _: & mut RuntimeContext , mut this : ClassInstanceRef < Self > ) -> Result < ( ) > {
99144 tracing:: debug!( "java.io.ByteArrayOutputStream::reset({this:?})" ) ;
100145
0 commit comments