Reputation: 3358
I am trying to define a js_sys::Promise
. The resolution of the promise should return a container buf
with all gathered ice candidates in a webrtc initialization.
let promise = js_sys::Promise::new(&mut |resolve: js_sys::Function, reject: js_sys::Function| {
let mut buf: Vec<RtcIceCandidate> = Vec::new();
let onicecandidate_callback = Closure::wrap(
Box::new(move |ev: RtcPeerConnectionIceEvent| match ev.candidate() {
Some(candidate) => {
buf.push(candidate);
}
None => {
// resolve promise here
resolve.call0(&buf.into())
}
}) as Box<dyn FnMut(RtcPeerConnectionIceEvent)>,
);
});
I am not sure how to convert buf
into a JsValue
which is required to call the resolve
function. I am getting the following error when trying to compile the code above:
error[E0277]: the trait bound `wasm_bindgen::JsValue: From<Vec<RtcIceCandidate>>` is not satisfied
--> src/lib.rs:529:43
|
529 | resolve.call0(&buffer.into());
| ^^^^ the trait `From<Vec<RtcIceCandidate>>` is not implemented for `wasm_bindgen::JsValue`
|
= help: the following implementations were found:
<wasm_bindgen::JsValue as From<&'a T>>
<wasm_bindgen::JsValue as From<&'a std::string::String>>
<wasm_bindgen::JsValue as From<&'a str>>
<wasm_bindgen::JsValue as From<ArrayBuffer>>
and 112 others
= note: required because of the requirements on the impl of `Into<wasm_bindgen::JsValue>` for `Vec<RtcIceCandidate>`
I have tried some alternative ways of converting buf:
resolve.call0(&JsValue::from(&buf));
This gives the error:
error[E0277]: the trait bound `Vec<RtcIceCandidate>: JsCast` is not satisfied
--> src/lib.rs:529:36
|
529 | resolve.call0(&JsValue::from(&buffer));
| ^^^^^^^^^^^^^ the trait `JsCast` is not implemented for `Vec<RtcIceCandidate>`
|
= note: required because of the requirements on the impl of `From<&Vec<RtcIceCandidate>>` for `wasm_bindgen::JsValue`
And JsValue::from_serde
requires that RtcIceCandidate
implements the Serialize
trait, which is not the case here.
Upvotes: 0
Views: 1027
Reputation: 8514
The problem is not with the RtcIceCandidate
, that derefs to JsValue
.
I've never used js-sys, so I may be wrong, but the problem seems to be that converting Vec
into js_sys::Array
must be done explicitly (maybe because it's expensive and needs one WASM→JS call per element?).
You can convert a Vec
to a JsValue
like this:
&buf.iter().collect::<Array>()
But I suspect that it would be better to work with the Array
directly.
use js_sys::Array;
use wasm_bindgen::prelude::Closure;
use web_sys::RtcPeerConnectionIceEvent;
fn foo() {
let _promise = js_sys::Promise::new(
&mut |resolve: js_sys::Function, _reject: js_sys::Function| {
let buf: Array = Array::new();
let _onicecandidate_callback = Closure::wrap(Box::new(
move |ev: RtcPeerConnectionIceEvent| match ev.candidate() {
Some(candidate) => {
buf.push(&candidate);
}
None => {
// resolve promise here
resolve.call0(&buf).unwrap();
}
},
)
as Box<dyn FnMut(RtcPeerConnectionIceEvent)>);
},
);
}
And the Cargo.toml
, in case anybody else wants to reproduce:
[dependencies]
web-sys = { version = "0.3.56", features = ["RtcIceCandidate", "RtcPeerConnectionIceEvent"] }
js-sys = "0.3.56"
wasm-bindgen = "0.2.79"
Upvotes: 1