use std::sync::OnceLock;
use futures_util::{future::RemoteHandle, FutureExt};
use wasm_bindgen_test::*;
#[web_rpc::service]
pub trait FortyTwo {
fn forty_two(&self) -> u32;
}
struct FortyTwoServiceImpl;
impl FortyTwo for FortyTwoServiceImpl {
fn forty_two(&self) -> u32 {
42
}
}
#[web_rpc::service]
pub trait Channel {
#[transfer(return)]
fn start(&self) -> web_sys::MessagePort;
}
#[derive(Default)]
struct ChannelServiceImpl {
server_handle: OnceLock<RemoteHandle<()>>,
}
impl Channel for ChannelServiceImpl {
fn start(&self) -> web_sys::MessagePort {
let channel = web_sys::MessageChannel::new().unwrap();
let (server, server_handle) = web_rpc::Interface::new(channel.port1())
.then(|interface| {
web_rpc::Builder::new(interface)
.with_service::<FortyTwoService<_>>(FortyTwoServiceImpl)
.build()
})
.remote_handle();
wasm_bindgen_futures::spawn_local(server);
self.server_handle
.set(server_handle)
.map_err(|_| "OnceLock already set")
.unwrap();
channel.port2()
}
}
#[wasm_bindgen_test]
async fn inception() {
console_error_panic_hook::set_once();
let channel = web_sys::MessageChannel::new().unwrap();
let (server_interface, client_interface) = futures_util::future::join(
web_rpc::Interface::new(channel.port1()),
web_rpc::Interface::new(channel.port2()),
)
.await;
let (server, _server_handle) = web_rpc::Builder::new(server_interface)
.with_service::<ChannelService<_>>(ChannelServiceImpl::default())
.build()
.remote_handle();
wasm_bindgen_futures::spawn_local(server);
let client = web_rpc::Builder::new(client_interface)
.with_client::<ChannelClient>()
.build();
let remote_client = client
.start()
.then(web_rpc::Interface::new)
.map(|interface| {
web_rpc::Builder::new(interface)
.with_client::<FortyTwoClient>()
.build()
})
.await;
assert_eq!(remote_client.forty_two().await, 42);
}