use crate::react_bindings;
use std::{
any::Any,
cell::{Ref, RefCell, RefMut},
fmt::Debug,
rc::Rc,
};
use wasm_bindgen::prelude::*;
#[doc(hidden)]
#[wasm_bindgen(js_name = __WasmReact_RefContainerValue)]
#[derive(Debug, Clone)]
pub struct RefContainerValue(pub(crate) Rc<dyn Any>);
impl RefContainerValue {
pub fn value<T: 'static>(&self) -> Result<Rc<T>, Rc<dyn Any>> {
Rc::downcast::<T>(self.0.clone())
}
}
#[derive(Debug)]
pub struct RefContainer<T>(Rc<RefCell<T>>);
impl<T: 'static> RefContainer<T> {
pub fn current(&self) -> Ref<'_, T> {
self.0.borrow()
}
pub fn current_mut(&mut self) -> RefMut<'_, T> {
self.0.borrow_mut()
}
pub fn set_current(&mut self, value: T) {
*self.current_mut() = value;
}
}
impl<T> Clone for RefContainer<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
pub fn use_ref<T: 'static>(init: T) -> RefContainer<T> {
let mut value = None;
react_bindings::use_rust_ref(
Closure::once(move || RefContainerValue(Rc::new(RefCell::new(init))))
.as_ref(),
&mut |ref_container_value| {
value = Some(
ref_container_value
.value::<RefCell<T>>()
.expect_throw("mismatched ref container type"),
);
},
);
RefContainer(value.expect_throw("callback was not called"))
}