use std::marker::PhantomData;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use wasm_bindgen::{JsCast, JsValue};
#[derive(Serialize, Deserialize)]
pub enum WireArg {
Js,
Bytes(Vec<u8>),
None,
Some(Box<WireArg>),
Ok(Box<WireArg>),
Err(Box<WireArg>),
Seq(Vec<WireArg>),
}
#[doc(hidden)]
pub trait __RpcJsEncode {
fn __rpc_encode(self, post: &js_sys::Array) -> WireArg;
}
impl<T: AsRef<JsValue> + ?Sized> __RpcJsEncode for &T {
fn __rpc_encode(self, post: &js_sys::Array) -> WireArg {
post.push(self.as_ref());
WireArg::Js
}
}
#[doc(hidden)]
pub trait __RpcSerialEncode {
fn __rpc_encode(self, post: &js_sys::Array) -> WireArg;
}
impl<T: Serialize + ?Sized> __RpcSerialEncode for &&T {
fn __rpc_encode(self, _post: &js_sys::Array) -> WireArg {
WireArg::Bytes(bincode::serialize(self).unwrap())
}
}
#[doc(hidden)]
pub struct Decoder<T: ?Sized>(PhantomData<T>);
impl<T: ?Sized> Default for Decoder<T> {
fn default() -> Self {
Decoder(PhantomData)
}
}
#[doc(hidden)]
pub trait __RpcJsDecode<T> {
fn __rpc_decode(self, wire: WireArg, post: &js_sys::Array) -> T;
}
impl<T: JsCast> __RpcJsDecode<T> for &Decoder<T> {
fn __rpc_decode(self, wire: WireArg, post: &js_sys::Array) -> T {
match wire {
WireArg::Js => post.shift().dyn_into::<T>().unwrap(),
_ => panic!("web_rpc: wire/type mismatch — expected Js variant"),
}
}
}
#[doc(hidden)]
pub trait __RpcSerialDecode<T> {
fn __rpc_decode(self, wire: WireArg, post: &js_sys::Array) -> T;
}
impl<T: DeserializeOwned> __RpcSerialDecode<T> for &&Decoder<T> {
fn __rpc_decode(self, wire: WireArg, _post: &js_sys::Array) -> T {
match wire {
WireArg::Bytes(b) => bincode::deserialize(&b).unwrap(),
_ => panic!("web_rpc: wire/type mismatch — expected Bytes variant"),
}
}
}