Returning a Rust Vec<Vec<i32>> to JavaScript via WebAssembly

Viewed 875

I am working on a project involving Rust and WebAssembly using the "wasm32-unknown-unknown" target. It is no problem to return a Vec<i32> from my Rust code using this function:

#[no_mangle]
pub extern "C" fn calc_vector() -> usize {
    unsafe {
        vec_len = 0;
    }

    let mut data: Vec<i32> = Vec::new();

    for i in 0..1000 {
        data.push(i);
    }

    unsafe {
        vec_len = data.len();
    }

    data.as_mut_ptr() as usize
}

This returns an offset and I call another function from JS to get the length of my Vec. I then build the Vector in JavaScript again (knowing that i32 -> 4x uint8):

let vec_addr = exports.calc_vector();
let vec_len = exports.get_vec_len();

while(arr.length < vec_len) {
    let numberUint8 = new DataView(view.buffer, vec_addr, 4);
    let number = numberUint8.getInt32(0, true);
    arr.push(number)

    // move to next value in vector
    vec_addr += 4;
}

Using this, I want to create a Rust function that returns a Vec<Vec<i32>>, however, it just won't work:

#[no_mangle]
pub extern "C" fn calc_vector_in_vector() -> usize {
    unsafe {
        vec_len = 0;
        elements_in_vect = 0;
    }

    let mut outer_vec: Vec<*mut i32> = Vec::new();
    let mut inner_vec: Vec<i32> = Vec::new();

    for i in 0..100 {
        inner_vec.push(i);
        unsafe {
            elements_in_vect += 1;
        }
    }

    outer_vec.push(inner_vec.as_mut_ptr());

    unsafe {
        vec_len = outer_vec.len();
    }

    outer_vec.as_mut_ptr() as usize
}

I thought that I could use the same logic as with a single Vec: at the address returned from calc_vector_in_vector() is the first entry of the outer vector, containing the address as i32 of the first element of the inner vector (an actual number). However, on this address there seems to be nonsense. What I am doing wrong here?

1 Answers

Because the vectors in my vector are all the same length, I can use the lazy_static crate to initialize a static Vec wrapped in a Mutex (to be able to alter it later on). LEN_VEC is the length of the vector and SIZE_INNER_VEC the size of one vector in my static vector.

I then add i32 to the static vector and return the address of the Vec using ARRAY.lock().unwrap().as_mut_ptr() as usize. With SIZE_INNER_VEC and LEN_VEC, I can recreate the vectors in my vector in JavaScript.

static mut LEN_VEC: usize = 0;
static mut SIZE_INNER_VEC: usize = 0;

lazy_static! {
    // Wrap in Mutex to change later on
    static ref ARRAY: Mutex<Vec<i32>> = Mutex::new(vec![]);
}

pub fn vector_in_vector() -> usize {
    //set LEN_VEC
    //set SIZE_INNER_VEC

    ARRAY.lock().unwrap().as_mut_ptr() as usize
}
Related