You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Question: How to send Uint8Array from Rust to JavaScript fast #322
Hello! I am currently researching the possibility of using Deno's WebGPU functionality on Adobe Illustrator using rustyscript.
I've been touching the current rustyscript API and it seems that json_args! does not allow me to pass large binary data like ArrayBuffer or Uint8Array to the TypeScript runtime without converting it to JSON. (It doesn't look like it would be easy from TypeScript to Rust either)
Some APIs like Deno.readFile in Deno seem to be able to transfer huge data from the Rust side to the TypeScript runtime, but how can we do the equivalent in rustyscript?
Hello
Did you use v8::Value to build the value you want to pass?
Can you provide an example so I could help? replit or any similar thing would be nice.
Here how would I do the thing. It takes less then 4ms on debug mode on my machine.
My example a bit clumsy but it's more like a proof of concept so you need to think how you can apply to your code.
@utyfua
Thank you! I wanted to do exactly what this sample does!
I wasn't familiar with the V8 API, so this was really helpful!
I was able to exchange ArrayBuffers between Rust and JavaScript using your sample code!
I'll write some sample code to help other users too!
use deno_core::v8;use tokio::time::Instant;///!///! This example is meant to demonstrate the large-binary data conversion between Rust and JavaScript///!///! - Converting Rust Vec<u8> to JavaScript ArrayBuffer///! - Passing large array data between Rust and JavaScript runtime///! - Memory efficient handling of binary data across language boundaries///! - Direct memory mapping using V8 ArrayBuffer///!///! The example creates a large binary data, converts it to a JavaScript///! Uint8Array, and verifies the roundtrip conversion integrity///!use rustyscript::{js_value,Error,Runtime};fnmain() -> Result<(),Error>{letmut input_data = "Some Data".repeat(10_000_000).as_bytes().to_vec();let input_data_orig = input_data.clone();letmut runtime = Runtime::new(Default::default())?;let t = Instant::now();let fn_ref = runtime
.eval::<js_value::Value>(r#"(input)=>{ return new Uint8Array(input); }"#)?
.into_v8();let scope = &mut runtime.deno_runtime().handle_scope();let array_buffer = to_array_buffer(scope, input_data).unwrap();let fn_ref = v8::Local::<v8::Value>::new(scope, fn_ref);let fn_ref = v8::Local::<v8::Function>::try_from(fn_ref).unwrap();let args = vec![array_buffer.into()];let js_result = fn_ref.call(scope, fn_ref.into(),&args).unwrap();let output_data = extract_uint8_array(scope, js_result).unwrap();println!("Time taken: {:?}", t.elapsed());println!("{}", input_data_orig.iter().zip(output_data.iter()).all(|(a, b)| a == b));Ok(())}fnto_array_buffer<'a>(scope:&mut v8::HandleScope<'a>,value:Vec<u8>) -> Option<v8::Local<'a,v8::ArrayBuffer>>{let ab = v8::ArrayBuffer::with_backing_store(
scope,&v8::ArrayBuffer::new_backing_store_from_bytes(value).make_shared(),);Some(ab.into())}fnextract_uint8_array(scope:&mut v8::HandleScope,value: v8::Local<v8::Value>) -> Option<Vec<u8>>{if !value.is_uint8_array(){returnNone;}let uint8array = value.try_cast::<v8::Uint8Array>().unwrap();let ab = uint8array.buffer(scope).unwrap();let buf = ab.get_backing_store().to_owned();let len = ab.byte_length();if len == 0{returnSome(vec![]);}Some(unsafe{
std::slice::from_raw_parts_mut(
buf.data().unwrap().cast::<u8>().as_ptr(),
len
).into()})}
Activity
utyfua commentedon Feb 12, 2025
Hello
Did you use
v8::Valueto build the value you want to pass?Can you provide an example so I could help? replit or any similar thing would be nice.
utyfua commentedon Feb 12, 2025
Here how would I do the thing. It takes less then 4ms on debug mode on my machine.
My example a bit clumsy but it's more like a proof of concept so you need to think how you can apply to your code.
rscarson commentedon Feb 12, 2025
Perhaps a new js_value variant is warranted?
utyfua commentedon Feb 12, 2025
I dont thing so. You can mix with using rusy v8 api anytime just like I did this time.
Also if you need performance
v8::Localwill be much better then converting it tov8:Globaleach time you need any atomic operation.To be honest I am using
rustyscript::js_valueonly to getv8::Globalso I can convert it tov8::Local(not in this example but in general)hanakla commentedon Feb 13, 2025
@utyfua
Thank you! I wanted to do exactly what this sample does!
I wasn't familiar with the V8 API, so this was really helpful!
I was able to exchange ArrayBuffers between Rust and JavaScript using your sample code!
I'll write some sample code to help other users too!
utyfua commentedon Feb 13, 2025
@hanakla I dont like the use of unsafe.
I think you dont fully understand how can you use
v8::BackingStoreto get the data from v8. You already have reference to the data.Here one more example which modifies existing one and creates a new one.
rscarson commentedon Feb 13, 2025
A pr with that added to examples, or even the book would be appreciated
utyfua commentedon Feb 13, 2025
Do you think its possible to comeup with some cookbook or something for the buffers?
There a lot of things what you can do. Most of them is specific for each case, dont you think?
Besides, I don't have time to work on such big project right now. After I settle down I'll try to make my contribution.