use super::{JsValue, js_sys};
pub trait Post: AsJs {
fn transferables(&self) -> js_sys::Array {
js_sys::Array::new()
}
}
pub trait PostExt {
fn post(&self, message: impl Post) -> Result<(), JsValue>;
}
impl PostExt for web_sys::MessagePort {
fn post(&self, message: impl Post) -> Result<(), JsValue> {
#![allow(clippy::needless_pass_by_value)]
self.post_message_with_transferable(&message.to_js()?, &message.transferables())
}
}
impl PostExt for web_sys::Worker {
fn post(&self, message: impl Post) -> Result<(), JsValue> {
#![allow(clippy::needless_pass_by_value)]
self.post_message_with_transfer(&message.to_js()?, &message.transferables())
}
}
#[derive(serde::Serialize)]
pub struct Postable {
#[serde(with = "serde_wasm_bindgen::preserve")]
message: JsValue,
#[serde(with = "serde_wasm_bindgen::preserve")]
transfer: js_sys::Array,
}
impl Postable {
pub fn new(message: impl Post) -> Result<Self, JsValue> {
#![allow(clippy::needless_pass_by_value)]
Ok(Self {
message: message.to_js()?,
transfer: message.transferables(),
})
}
}
pub trait AsJs {
fn to_js(&self) -> Result<JsValue, JsValue>;
fn from_js(js_value: JsValue) -> Result<Self, JsValue>
where
Self: Sized;
}
impl<T: serde::Serialize + serde::de::DeserializeOwned> AsJs for T {
fn to_js(&self) -> Result<JsValue, JsValue> {
Ok(serde_wasm_bindgen::to_value(self)?)
}
fn from_js(value: JsValue) -> Result<Self, JsValue>
where
Self: Sized,
{
Ok(serde_wasm_bindgen::from_value(value)?)
}
}
impl Post for () {}
impl Post for u8 {}
impl Post for u16 {}
impl Post for u32 {}
impl Post for u64 {}
impl Post for u128 {}
impl Post for i8 {}
impl Post for i16 {}
impl Post for i32 {}
impl Post for i64 {}
impl Post for i128 {}
impl Post for String {}
impl<T: Post, E: Post> Post for Result<T, E>
where
Result<T, E>: AsJs,
{
fn transferables(&self) -> js_sys::Array {
match self {
Ok(x) => x.transferables(),
Err(e) => e.transferables(),
}
}
}
impl<T: Post, U: Post> Post for (T, U)
where
(T, U): AsJs,
{
fn transferables(&self) -> js_sys::Array {
let mut array = js_sys::Array::new();
array = array.concat(&self.0.transferables());
array = array.concat(&self.1.transferables());
array
}
}
impl<T: Post> Post for Vec<T>
where
Vec<T>: AsJs,
{
fn transferables(&self) -> js_sys::Array {
let mut array = js_sys::Array::new();
for x in self {
array = array.concat(&x.transferables());
}
array
}
}