lib.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. use std::{
  2. cell::{Ref, RefMut},
  3. fmt::Display,
  4. marker::PhantomData,
  5. ops::{Add, Div, Mul, Sub},
  6. };
  7. mod rt;
  8. use dioxus_core::ScopeState;
  9. pub use rt::*;
  10. use crate::rt::claim_rt;
  11. pub fn use_init_signal_rt(cx: &ScopeState) {
  12. cx.use_hook(|| {
  13. let rt = claim_rt(cx.schedule_update_any());
  14. cx.provide_context(rt);
  15. });
  16. }
  17. pub fn use_signal<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal<T> {
  18. cx.use_hook(|| {
  19. let rt: &'static SignalRt = match cx.consume_context() {
  20. Some(rt) => rt,
  21. None => cx.provide_context(claim_rt(cx.schedule_update_any())),
  22. };
  23. let id = rt.init(f());
  24. rt.subscribe(id, cx.scope_id());
  25. struct SignalHook<T> {
  26. signal: Signal<T>,
  27. }
  28. impl<T> Drop for SignalHook<T> {
  29. fn drop(&mut self) {
  30. self.signal.rt.remove(self.signal.id);
  31. }
  32. }
  33. SignalHook {
  34. signal: Signal {
  35. id,
  36. rt,
  37. t: PhantomData,
  38. },
  39. }
  40. })
  41. .signal
  42. }
  43. pub struct Signal<T> {
  44. id: usize,
  45. rt: &'static SignalRt,
  46. t: PhantomData<T>,
  47. }
  48. impl<T: 'static> Signal<T> {
  49. pub fn read(&self) -> Ref<T> {
  50. self.rt.read(self.id)
  51. }
  52. pub fn write(&self) -> RefMut<T> {
  53. self.rt.write(self.id)
  54. }
  55. pub fn set(&mut self, value: T) {
  56. self.rt.set(self.id, value);
  57. }
  58. pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
  59. let write = self.read();
  60. f(&*write)
  61. }
  62. pub fn update<O>(&self, _f: impl FnOnce(&mut T) -> O) -> O {
  63. let mut write = self.write();
  64. _f(&mut *write)
  65. }
  66. }
  67. impl<T: Clone + 'static> Signal<T> {
  68. pub fn get(&self) -> T {
  69. self.rt.get(self.id)
  70. }
  71. }
  72. impl<T: Clone + 'static> std::ops::Deref for Signal<T> {
  73. type Target = dyn Fn() -> T;
  74. fn deref(&self) -> &Self::Target {
  75. self.rt.getter(self.id)
  76. }
  77. }
  78. impl<T> std::clone::Clone for Signal<T> {
  79. fn clone(&self) -> Self {
  80. Self {
  81. t: PhantomData,
  82. id: self.id,
  83. rt: self.rt,
  84. }
  85. }
  86. }
  87. impl<T> Copy for Signal<T> {}
  88. impl<T: Display + 'static> Display for Signal<T> {
  89. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  90. self.rt.with::<T, _>(self.id, |v| T::fmt(v, f))
  91. }
  92. }
  93. impl<T: Add<Output = T> + Copy + 'static> std::ops::AddAssign<T> for Signal<T> {
  94. fn add_assign(&mut self, rhs: T) {
  95. self.set(self.get() + rhs);
  96. }
  97. }
  98. impl<T: Sub<Output = T> + Copy + 'static> std::ops::SubAssign<T> for Signal<T> {
  99. fn sub_assign(&mut self, rhs: T) {
  100. self.set(self.get() - rhs);
  101. }
  102. }
  103. impl<T: Mul<Output = T> + Copy + 'static> std::ops::MulAssign<T> for Signal<T> {
  104. fn mul_assign(&mut self, rhs: T) {
  105. self.set(self.get() * rhs);
  106. }
  107. }
  108. impl<T: Div<Output = T> + Copy + 'static> std::ops::DivAssign<T> for Signal<T> {
  109. fn div_assign(&mut self, rhs: T) {
  110. self.set(self.get() / rhs);
  111. }
  112. }