1use std::{cell::RefCell, rc::Rc};
2
3use crate::{IntoRc, IntoRefValue, ReadRef, WriteRef};
4
5pub fn use_ref<T: 'static + ?Sized>(initial_value: Rc<T>) -> MutableRefRc<T> {
6 let rc = crate::use_ref_cell(initial_value);
7 MutableRefRc(rc)
8}
9
10pub fn use_ref_with<T: 'static + ?Sized, F: FnOnce() -> Rc<T>>(
11 get_initial_value: F,
12) -> MutableRefRc<T> {
13 let ref_cell = super::use_ref_cell_with::<Rc<T>, _>(move || get_initial_value().into_rc());
14 MutableRefRc(ref_cell)
15}
16
17pub fn use_ref_set_as<T: 'static + ?Sized>(value: Rc<T>) -> MutableRefRc<T> {
38 let ref_value = use_ref(Rc::clone(&value));
39 if !Rc::ptr_eq(&*ref_value.0 .0.borrow(), &value) {
40 ref_value.set_current(value)
41 }
42 ref_value
43}
44
45pub struct MutableRefRc<T: ?Sized>(super::ReadRefRc<RefCell<Rc<T>>>);
46
47impl<T: ?Sized + std::fmt::Debug> std::fmt::Debug for MutableRefRc<T> {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 let v = self.0 .0.borrow();
50 let v = &**v;
51 f.debug_tuple("MutableRefRc").field(&v).finish()
52 }
53}
54
55impl<T: ?Sized> PartialEq for MutableRefRc<T> {
56 fn eq(&self, other: &Self) -> bool {
57 self.0 == other.0
58 }
59}
60
61impl<T: ?Sized> Eq for MutableRefRc<T> {}
62
63impl<T: ?Sized> Clone for MutableRefRc<T> {
64 fn clone(&self) -> Self {
65 Self(self.0.clone())
66 }
67}
68
69impl<T: ?Sized> ReadRef<Rc<T>> for MutableRefRc<T> {
70 #[inline]
71 fn current(&self) -> Rc<T> {
72 let a = self.0 .0.borrow();
73 Rc::clone(&*a)
74 }
75}
76
77impl<T: ?Sized, S: IntoRefValue<Rc<T>>> WriteRef<S> for MutableRefRc<T> {
78 #[inline]
79 fn set_current(&self, v: S) {
80 let v: Rc<T> = v.into_ref_value();
81 let mut a = self.0 .0.borrow_mut();
82 *a = v;
83 }
84}
85
86impl<T> crate::SafeIntoJsRuntime for MutableRefRc<T>
87where
88 dyn Fn(T): wasm_bindgen::closure::WasmClosure,
89 T: 'static,
90{
91 fn safe_into_js_runtime(self) -> crate::PassedToJsRuntime {
92 crate::AnyFn::new(move |v| self.set_current(v)).safe_into_js_runtime()
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use std::rc::Rc;
99
100 use super::super::WriteRef;
101 use super::MutableRefRc;
102
103 #[test]
104 fn auto_impl_write_ref() {
105 let _func_rc: fn(&MutableRefRc<i32>, v: Rc<i32>) =
106 <MutableRefRc<i32> as WriteRef<Rc<i32>>>::set_current;
107 let _func: fn(&MutableRefRc<i32>, v: i32) =
108 <MutableRefRc<i32> as WriteRef<i32>>::set_current;
109 }
110}