use std::ops::Deref;
use std::rc::Rc;
use async_trait::async_trait;
use derivative::Derivative;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::spawn_local;
use crate::js::perspective::*;
use crate::utils::ApiResult;
#[derive(Derivative)]
#[derivative(Clone(bound = ""))]
pub struct PerspectiveOwned<T>(Rc<PerspectiveOwnedSession<T>>)
where
T: AsyncDelete + JsCast + 'static;
pub type View = PerspectiveOwned<JsPerspectiveView>;
#[allow(dead_code)]
pub type Table = PerspectiveOwned<JsPerspectiveTable>;
impl<T> PerspectiveOwned<T>
where
T: AsyncDelete + JsCast + 'static,
{
pub fn new(obj: T) -> Self {
Self(Rc::new(PerspectiveOwnedSession(obj)))
}
pub fn as_jsvalue(&self) -> JsValue {
self.0 .0.as_ref().unchecked_ref::<JsValue>().clone()
}
pub fn js_get(&self) -> T {
self.as_jsvalue().unchecked_into::<T>()
}
}
impl<T> Deref for PerspectiveOwned<T>
where
T: AsyncDelete + JsCast + 'static,
{
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0 .0
}
}
struct PerspectiveOwnedSession<T: AsyncDelete + JsCast + 'static>(T);
#[async_trait(?Send)]
impl<T: AsyncDelete + JsCast + 'static> Drop for PerspectiveOwnedSession<T> {
fn drop(&mut self) {
let obj = self
.0
.unchecked_ref::<JsValue>()
.clone()
.unchecked_into::<T>();
spawn_local(async move {
obj.delete()
.await
.expect("Failed to delete perspective object");
});
}
}
#[async_trait(?Send)]
pub trait AsyncDelete {
async fn delete(self) -> ApiResult<JsValue>;
}
#[async_trait(?Send)]
impl AsyncDelete for JsPerspectiveView {
async fn delete(self) -> ApiResult<JsValue> {
self.delete().await?;
Ok(JsValue::UNDEFINED)
}
}
#[async_trait(?Send)]
impl AsyncDelete for JsPerspectiveTable {
async fn delete(self) -> ApiResult<JsValue> {
self.delete().await?;
Ok(JsValue::UNDEFINED)
}
}