From 16b5eebe234cdfa70dfff66a58d8bf4e0458727f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 17 May 2022 16:18:10 +0200 Subject: [PATCH] feat(crypto): Implement a hacky `downcast` function. --- crates/matrix-sdk-crypto/src/js/mod.rs | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/matrix-sdk-crypto/src/js/mod.rs b/crates/matrix-sdk-crypto/src/js/mod.rs index 0e8112fcf..e3833d1f5 100644 --- a/crates/matrix-sdk-crypto/src/js/mod.rs +++ b/crates/matrix-sdk-crypto/src/js/mod.rs @@ -7,3 +7,34 @@ pub mod machine; pub mod requests; pub mod responses; pub mod sync_events; + +use js_sys::{Object, Reflect}; +use wasm_bindgen::{convert::RefFromWasmAbi, prelude::*}; + +/// A really hacky and dirty code to downcast a `JsValue` to `T: +/// RefFromWasmAbi`, inspired by +/// https://github.com/rustwasm/wasm-bindgen/issues/2231#issuecomment-656293288. +/// +/// The returned value is a likely to be `wasm_bindgen::__ref::Ref`. +fn downcast(value: &JsValue, classname: &str) -> Result +where + T: RefFromWasmAbi, +{ + let constructor_name = Object::get_prototype_of(&value).constructor().name(); + + if constructor_name == classname { + let pointer = Reflect::get(value, &JsValue::from_str("ptr")) + .map_err(|_| JsError::new("Failed to read the `JsValue` pointer"))?; + let pointer = pointer + .as_f64() + .ok_or_else(|| JsError::new("Failed to read the `JsValue` pointer as a `f64`"))? + as u32; + + Ok(unsafe { T::ref_from_abi(pointer) }) + } else { + Err(JsError::new(&format!( + "Expect an `{}` instance, received `{}` instead", + classname, constructor_name, + ))) + } +}