use serde::de::DeserializeOwned;
use crate::error::Error;
mod wasm;
pub fn subscribe<Event, Handler>(event: &str, handler: Handler) -> Result<Subscription, Error>
where
Event: DeserializeOwned + 'static,
Handler: Fn(Event) + 'static,
{
subscribe_impl(event, handler)
}
pub struct Subscription {
#[cfg(target_arch = "wasm32")]
inner: Option<Box<dyn Teardown>>,
}
#[cfg(target_arch = "wasm32")]
pub(crate) trait Teardown {
fn remove(self: Box<Self>);
fn forget(self: Box<Self>);
}
impl Subscription {
pub fn forget(self) {
#[cfg(target_arch = "wasm32")]
{
let mut this = self;
if let Some(inner) = this.inner.take() {
inner.forget();
}
}
}
#[cfg(target_arch = "wasm32")]
pub(crate) fn from_inner(inner: Box<dyn Teardown>) -> Self {
Self { inner: Some(inner) }
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn inert() -> Self {
Self {}
}
}
impl Drop for Subscription {
fn drop(&mut self) {
#[cfg(target_arch = "wasm32")]
if let Some(inner) = self.inner.take() {
inner.remove();
}
}
}
#[cfg(target_arch = "wasm32")]
fn subscribe_impl<Event, Handler>(event: &str, handler: Handler) -> Result<Subscription, Error>
where
Event: DeserializeOwned + 'static,
Handler: Fn(Event) + 'static,
{
wasm::subscribe(event, handler).map(|inner| Subscription::from_inner(Box::new(inner)))
}
#[cfg(not(target_arch = "wasm32"))]
fn subscribe_impl<Event, Handler>(_event: &str, _handler: Handler) -> Result<Subscription, Error>
where
Event: DeserializeOwned + 'static,
Handler: Fn(Event) + 'static,
{
Ok(Subscription::inert())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn non_wasm_subscribe_stubs_to_ok() {
let subscription = subscribe::<serde_json::Value, _>("score_update", |_| {}).unwrap();
drop(subscription);
}
#[test]
fn non_wasm_forget_is_noop() {
let subscription = subscribe::<serde_json::Value, _>("score_update", |_| {}).unwrap();
subscription.forget();
}
}