wasm_react/
prop_container.rs

1use crate::hooks::{DeferredValue, Memo, RefContainer, State};
2use std::{
3  cell::{Ref, RefCell},
4  ops::Deref,
5  rc::Rc,
6};
7
8/// Allows read-only access to the underlying value of [`PropContainer`].
9#[non_exhaustive]
10#[derive(Debug)]
11pub enum PropContainerRef<'a, T> {
12  #[allow(missing_docs)]
13  Simple(&'a T),
14  #[allow(missing_docs)]
15  Ref(Ref<'a, T>),
16}
17
18impl<T> PropContainerRef<'_, T> {
19  /// Clones the reference.
20  pub fn clone(orig: &Self) -> Self {
21    match orig {
22      PropContainerRef::Simple(x) => PropContainerRef::Simple(x),
23      PropContainerRef::Ref(x) => PropContainerRef::Ref(Ref::clone(x)),
24    }
25  }
26}
27
28impl<T> Deref for PropContainerRef<'_, T> {
29  type Target = T;
30
31  fn deref(&self) -> &Self::Target {
32    match &self {
33      PropContainerRef::Simple(x) => x,
34      PropContainerRef::Ref(x) => x.deref(),
35    }
36  }
37}
38
39macro_rules! define_value_container {
40  {
41    $(
42      $Variant:ident($id:ident: $Ty:ty) => $RefVariant:ident($expr:expr) $(,)?
43    )*
44  } => {
45    /// A helpful abstraction over non-`Copy` types that can be used as a prop
46    /// type for components.
47    ///
48    /// Can contain all hook containers, [`Rc<T>`], and [`Rc<RefCell<T>>`].
49    #[non_exhaustive]
50    #[derive(Debug)]
51    pub enum PropContainer<T> {
52      $(
53        #[allow(missing_docs)]
54        $Variant($Ty),
55      )*
56    }
57
58    impl<T: 'static> PropContainer<T> {
59      /// Returns a read-only reference to the underlying value.
60      pub fn value(&self) -> PropContainerRef<'_, T> {
61        match self {
62          $( Self::$Variant($id) => PropContainerRef::$RefVariant($expr), )*
63        }
64      }
65    }
66
67    impl<T> Clone for PropContainer<T> {
68      fn clone(&self) -> Self {
69        match self {
70          $( Self::$Variant(x) => Self::$Variant(x.clone()), )*
71        }
72      }
73    }
74
75    $(
76      impl<T> From<$Ty> for PropContainer<T> {
77        fn from(value: $Ty) -> Self {
78          Self::$Variant(value)
79        }
80      }
81    )*
82  };
83}
84
85define_value_container! {
86  Rc(x: Rc<T>) => Simple(x.deref()),
87  RcRefCell(x: Rc<RefCell<T>>) => Ref(x.borrow()),
88  RefContainer(x: RefContainer<T>) => Ref(x.current()),
89  State(x: State<T>) => Ref(x.value()),
90  Memo(x: Memo<T>) => Ref(x.value()),
91  DeferredValue(x: DeferredValue<T>) => Ref(x.value()),
92}
93
94impl<T: PartialEq + 'static> PartialEq for PropContainer<T> {
95  fn eq(&self, other: &Self) -> bool {
96    T::eq(&self.value(), &other.value())
97  }
98}
99
100impl<T: PartialEq + 'static> PartialEq<T> for PropContainer<T> {
101  fn eq(&self, other: &T) -> bool {
102    T::eq(&self.value(), other)
103  }
104}
105
106impl<T> From<T> for PropContainer<T> {
107  fn from(value: T) -> Self {
108    Self::from(Rc::new(value))
109  }
110}