Wasm-bindgen: How to iterate `Uint8Array` on Rust

Created on 9 Jan 2019  路  8Comments  路  Source: rustwasm/wasm-bindgen

Hello! I am trying to convert a Uint8Array to a Vec<u8>, however I am having problems to iterate it and get the values.

Example code:

pub trait JsPacketManipulation {
    fn to_vec_u8(&self) -> Vec<u8>;
}

impl JsPacketManipulation for Uint8Array {
    fn to_vec_u8(&self) -> Vec<u8> {
        let mut vec: Vec<u8> = vec![];

        self.for_each(&mut |byte: u8, _length: u32, _array: Uint8Array| {
            vec.push(byte);
        });

        vec
    }
}

This code compiles, however it leads to this error on the browser: Uncaught TypeError: getObject(...).forEach is not a function.

I've also tried using try_iter, but I couldn't convert the JsValue to an u8 :slightly_frowning_face:

pub trait JsPacketManipulation {
    fn to_vec_u8(&self) -> Vec<u8>;
}

impl JsPacketManipulation for Uint8Array {
    fn to_vec_u8(&self) -> Vec<u8> {
        let mut vec: Vec<u8> = vec![];

        let iterator = js_sys::try_iter(self).unwrap().ok_or_else(|| {
            "need to pass iterable JS values!"
        }).unwrap();

        for byte in iterator {
            vec.push(byte.unwrap().into());
        }

        vec
    }
}

This other example doesn't compile, and it leads to this error on cargo:

error[E0277]: the trait bound `u8: std::convert::From<wasm_bindgen::JsValue>` is not satisfied
  --> src/packet/manipulation.rs:63:36
   |
63 |             vec.push(byte.unwrap().into());
   |                                    ^^^^ the trait `std::convert::From<wasm_bindgen::JsValue>` is not implemented for `u8`
   |
   = help: the following implementations were found:
             <u8 as std::convert::From<bool>>
             <u8 as std::convert::From<std::num::NonZeroU8>>
   = note: required because of the requirements on the impl of `std::convert::Into<u8>` for `wasm_bindgen::JsValue`

Most helpful comment

Thanks for the report @otaviopace and helping to narrow this doen @chinedufn! I've hopefully made it a bit easier to test this out and I've just gone ahead and published a new version of everything :)

All 8 comments

Would Uint8Array::copy_to fit your use case?

Maybe something along the lines of:

let uint8array = Uint8Array::new();
let mut slice = vec![0; uint8array.length()];
uint8array.copy_to(&mut slice[..])

I am using js_sys version 0.3.6, and the copy_to method was added on 0.3.7, however the method still isn't available somehow :thinking:

The error I am getting:

error[E0599]: no method named `copy_to` found for type `&js_sys::Uint8Array` in the current scope
  --> src/packet/manipulation.rs:55:14
   |
55 |         self.copy_to(&mut vec[..]);
   |              ^^^^^^^

Also @alexcrichton I don't know if you follow semver, but wouldn't it make more sense for this change to be a minor instead of a patch?

At this time, from what I can tell, wasm-bindgen is bundling most new API additions into patch versions, and if something really big comes along it gets a minor bump.

This is actually totally allowed by SemVer since wasm-bindgen hasn't hit 1.0.0 yet.

image

via https://semver.org/


I am using js_sys version 0.3.6, and the copy_to method was added on 0.3.7, however the method still isn't available somehow

You won't automatically get 0.3.7 if you already have 0.3.6 locally.

Quickest thing you can do is to go into your Cargo.toml and set js_sys = "0.3.7"

Hope that works!

We tried to update in Cargo.toml of js_sys from 0.3.6 to 0.3.7, and it doesn't work :slightly_frowning_face:

I even tried to use cargo clean to clear any cache but it didn't worked.

I've created a new project to verify that it wasn't some kind of cache, here it is the output:

screenshot-output

Gotcha. The only other thing that comes to mind is that it's possible that js-sys 0.3.7 was deployed before these slice changes landed.

image

Since the docs get built in CI on master it's possible for the docs to be a little ahead of what's actually live.

Can you set js-sys = { git = "https://github.com/rustwasm/wasm-bindgen", branch = "maser" } in your Cargo.toml and see if you still get an error?

Thanks for the report @otaviopace and helping to narrow this doen @chinedufn! I've hopefully made it a bit easier to test this out and I've just gone ahead and published a new version of everything :)

Thank you so much!!! It fixed the issue :slightly_smiling_face:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bantic picture bantic  路  4Comments

fitzgen picture fitzgen  路  4Comments

derekdreery picture derekdreery  路  3Comments

aschampion picture aschampion  路  4Comments

pauldorehill picture pauldorehill  路  3Comments