11use rquickjs:: class:: Trace ;
22use rquickjs:: Class ;
33use rquickjs:: Ctx ;
4+ use rquickjs:: Exception ;
45use rquickjs:: JsLifetime ;
6+ use rquickjs:: Object ;
57use rquickjs:: Result ;
68use rquickjs:: TypedArray ;
79use rquickjs:: Value ;
@@ -28,17 +30,62 @@ impl<'js> TextEncoder {
2830 }
2931
3032 pub fn encode ( & self , ctx : Ctx < ' js > , text : Value < ' js > ) -> Result < TypedArray < ' js , u8 > > {
31- let string = match text. as_string ( ) {
32- None => {
33- if let Some ( object) = text. as_object ( ) {
34- if let Some ( bytes) = object. as_typed_array :: < u8 > ( ) {
35- return Ok ( bytes. clone ( ) ) ;
36- }
37- }
38- "" . to_string ( )
33+ let string = Self :: string_from ( text) ?;
34+ TypedArray :: new ( ctx. clone ( ) , string. as_bytes ( ) )
35+ }
36+
37+ #[ qjs( rename = "encodeInto" ) ]
38+ pub fn encode_into (
39+ & self ,
40+ ctx : Ctx < ' js > ,
41+ text : Value < ' js > ,
42+ array : TypedArray < ' js , u8 > ,
43+ ) -> Result < Object < ' js > > {
44+ let string = Self :: string_from ( text) ?;
45+ let offset: usize = array. get ( "byteOffset" ) . unwrap_or_default ( ) ;
46+ let buffer = array
47+ . arraybuffer ( ) ?
48+ . as_raw ( )
49+ . ok_or ( Exception :: throw_message ( & ctx, "ArrayBuffer is detached" ) ) ?;
50+
51+ let mut read = 0 ;
52+ let mut written = 0 ;
53+ let max_len = buffer. len - offset;
54+ for char in string. chars ( ) {
55+ let len = char. len_utf8 ( ) ;
56+ if written + len > max_len {
57+ break ;
3958 }
59+ read += char. len_utf16 ( ) ;
60+ written += len;
61+ }
62+
63+ let bytes = & string. as_bytes ( ) [ ..written] ;
64+ unsafe {
65+ let buffer_ptr =
66+ std:: slice:: from_raw_parts_mut ( buffer. ptr . as_ptr ( ) . add ( offset) , written) ;
67+ buffer_ptr. copy_from_slice ( bytes) ;
68+ }
69+
70+ let obj = Object :: new ( ctx) ?;
71+ obj. set ( "read" , read) ?;
72+ obj. set ( "written" , written) ?;
73+ Ok ( obj)
74+ }
75+ }
76+
77+ impl TextEncoder {
78+ pub fn string_from ( text : Value < ' _ > ) -> Result < String > {
79+ let string = match text. as_string ( ) {
80+ None => text
81+ . as_object ( )
82+ . and_then ( |object| object. as_typed_array :: < u8 > ( ) )
83+ . and_then ( |array| array. as_bytes ( ) )
84+ . and_then ( |bytes| std:: str:: from_utf8 ( bytes) . ok ( ) )
85+ . map ( |s| s. to_string ( ) )
86+ . unwrap_or_default ( ) ,
4087 Some ( js_string) => js_string. to_string ( ) ?,
4188 } ;
42- TypedArray :: new ( ctx . clone ( ) , string. as_bytes ( ) )
89+ Ok ( string)
4390 }
4491}
0 commit comments