read_only_signal.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. use crate::{read::Readable, ReadableRef, Signal, SignalData};
  2. use dioxus_core::IntoDynNode;
  3. use std::ops::Deref;
  4. use crate::{default_impl, read_impls};
  5. use dioxus_core::{prelude::IntoAttributeValue, ScopeId};
  6. use generational_box::{Storage, UnsyncStorage};
  7. /// A signal that can only be read from.
  8. pub struct ReadOnlySignal<T: 'static, S: Storage<SignalData<T>> = UnsyncStorage> {
  9. inner: Signal<T, S>,
  10. }
  11. impl<T: 'static, S: Storage<SignalData<T>>> From<Signal<T, S>> for ReadOnlySignal<T, S> {
  12. fn from(inner: Signal<T, S>) -> Self {
  13. Self { inner }
  14. }
  15. }
  16. impl<T: 'static> ReadOnlySignal<T> {
  17. /// Create a new read-only signal.
  18. #[track_caller]
  19. pub fn new(signal: Signal<T>) -> Self {
  20. Self::new_maybe_sync(signal)
  21. }
  22. }
  23. impl<T: 'static, S: Storage<SignalData<T>>> ReadOnlySignal<T, S> {
  24. /// Create a new read-only signal that is maybe sync.
  25. #[track_caller]
  26. pub fn new_maybe_sync(signal: Signal<T, S>) -> Self {
  27. Self { inner: signal }
  28. }
  29. /// Get the scope that the signal was created in.
  30. pub fn origin_scope(&self) -> ScopeId {
  31. self.inner.origin_scope()
  32. }
  33. /// Get the id of the signal.
  34. pub fn id(&self) -> generational_box::GenerationalBoxId {
  35. self.inner.id()
  36. }
  37. #[doc(hidden)]
  38. /// This should only be used by the `rsx!` macro.
  39. pub fn __set(&mut self, value: T) {
  40. use crate::write::Writable;
  41. self.inner.set(value);
  42. }
  43. #[doc(hidden)]
  44. /// This should only be used by the `rsx!` macro.
  45. pub fn __take(&self) -> T {
  46. self.inner
  47. .manually_drop()
  48. .expect("Signal has already been dropped")
  49. }
  50. }
  51. impl<T, S: Storage<SignalData<T>>> Readable for ReadOnlySignal<T, S> {
  52. type Target = T;
  53. type Storage = S;
  54. #[track_caller]
  55. fn try_read_unchecked(
  56. &self,
  57. ) -> Result<ReadableRef<'static, Self>, generational_box::BorrowError> {
  58. self.inner.try_read_unchecked()
  59. }
  60. /// Get the current value of the signal. **Unlike read, this will not subscribe the current scope to the signal which can cause parts of your UI to not update.**
  61. ///
  62. /// If the signal has been dropped, this will panic.
  63. #[track_caller]
  64. fn peek_unchecked(&self) -> S::Ref<'static, T> {
  65. self.inner.peek_unchecked()
  66. }
  67. }
  68. #[cfg(feature = "serialize")]
  69. impl<T: serde::Serialize + 'static, Store: Storage<SignalData<T>>> serde::Serialize
  70. for ReadOnlySignal<T, Store>
  71. {
  72. fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
  73. self.read().serialize(serializer)
  74. }
  75. }
  76. #[cfg(feature = "serialize")]
  77. impl<'de, T: serde::Deserialize<'de> + 'static, Store: Storage<SignalData<T>>>
  78. serde::Deserialize<'de> for ReadOnlySignal<T, Store>
  79. {
  80. fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
  81. Ok(Self::new_maybe_sync(Signal::new_maybe_sync(
  82. T::deserialize(deserializer)?,
  83. )))
  84. }
  85. }
  86. impl<T> IntoAttributeValue for ReadOnlySignal<T>
  87. where
  88. T: Clone + IntoAttributeValue,
  89. {
  90. fn into_value(self) -> dioxus_core::AttributeValue {
  91. self.with(|f| f.clone().into_value())
  92. }
  93. }
  94. impl<T> IntoDynNode for ReadOnlySignal<T>
  95. where
  96. T: Clone + IntoDynNode,
  97. {
  98. fn into_dyn_node(self) -> dioxus_core::DynamicNode {
  99. self().into_dyn_node()
  100. }
  101. }
  102. impl<T: 'static, S: Storage<SignalData<T>>> PartialEq for ReadOnlySignal<T, S> {
  103. fn eq(&self, other: &Self) -> bool {
  104. self.inner == other.inner
  105. }
  106. }
  107. impl<T: Clone, S: Storage<SignalData<T>> + 'static> Deref for ReadOnlySignal<T, S> {
  108. type Target = dyn Fn() -> T;
  109. fn deref(&self) -> &Self::Target {
  110. Readable::deref_impl(self)
  111. }
  112. }
  113. read_impls!(
  114. ReadOnlySignal<T, S> where
  115. S: Storage<SignalData<T>>
  116. );
  117. default_impl!(
  118. ReadOnlySignal<T, S> where
  119. S: Storage<SignalData<T>>
  120. );
  121. impl<T: 'static, S: Storage<SignalData<T>>> Clone for ReadOnlySignal<T, S> {
  122. fn clone(&self) -> Self {
  123. *self
  124. }
  125. }
  126. impl<T: 'static, S: Storage<SignalData<T>>> Copy for ReadOnlySignal<T, S> {}