Skip to content

Allow Serde to bind Uint8Array to Vec<u8> #2017

@zer0x64

Description

@zer0x64

Not sure if this should be considered as a feature or a bug...

Motivation

Currently, wasm-bindgen bind Vec<u8> return type to Uint8Array on the javascript type. However, when using into_serde() to pass the data to the Rust side, the method returns an error when parsing a Uint8Array into a Vec<u8>.

#[wasm_bindgen]
pub fn test_serde(data: JsValue)-> Vec<u8> {
    let test: Vec<u8> = data.into_serde().expect("This will crash if the input is a Uint8Array");
    test
}

Although the solution in a simple case like this is to simply take a Vec<u8> directly as an input, this doesn't work for more complex type. A hack around it wouild be to convert the Uint8Array into an Array on the rust side:

// This works with either an Array or a Uint8Array
#[wasm_bindgen]
pub fn test_serde(data: JsValue)-> Vec<u8> {
    let data = if JsCast::is_instance_of::<Uint8Array>(&data) {
        JsValue::from(Array::from(&data))
    }
    else {
        data
    };

    let test: Vec<u8> = data.into_serde().unwrap();
    test
}

My specific type context was to receive a Vec<Vec<u8>>, which would be of the type Array<Uint8Array> from the Javascript side. I'll be dumping the code snippet of the hack here in case someone else need it:

fn test(values: Array) {
    let values = JsValue::from(values.map(&mut |v, _, _| {
        if JsCast::is_instance_of::<Uint8Array>(&v) {
            JsValue::from(Array::from(&v))
        }
        else {
            v
        }
    }));
    //...
}

This does work, but is pretty ugly. From a user perspective, it makes sense that deserializing a Uint8Array into a Vec<u8> should work without this boilerplate.

Alternatives

For the moment, I'm using the hack described above.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions