rt.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. use std::cell::{Ref, RefMut};
  2. use std::rc::Rc;
  3. use dioxus_core::prelude::{
  4. consume_context, consume_context_from_scope, current_scope_id, provide_context_to_scope,
  5. provide_root_context,
  6. };
  7. use dioxus_core::ScopeId;
  8. use generational_box::{GenerationalBox, Owner, Store};
  9. fn current_store() -> Store {
  10. match consume_context() {
  11. Some(rt) => rt,
  12. None => {
  13. let store = Store::default();
  14. provide_root_context(store).expect("in a virtual dom")
  15. }
  16. }
  17. }
  18. fn current_owner() -> Rc<Owner> {
  19. match consume_context() {
  20. Some(rt) => rt,
  21. None => {
  22. let owner = Rc::new(current_store().owner());
  23. provide_root_context(owner).expect("in a virtual dom")
  24. }
  25. }
  26. }
  27. fn owner_in_scope(scope: ScopeId) -> Rc<Owner> {
  28. match consume_context_from_scope(scope) {
  29. Some(rt) => rt,
  30. None => {
  31. let owner = Rc::new(current_store().owner());
  32. provide_context_to_scope(scope, owner).expect("in a virtual dom")
  33. }
  34. }
  35. }
  36. /// CopyValue is a wrapper around a value to make the value mutable and Copy.
  37. ///
  38. /// It is internally backed by [`generational_box::GenerationalBox`].
  39. pub struct CopyValue<T: 'static> {
  40. pub(crate) value: GenerationalBox<T>,
  41. origin_scope: ScopeId,
  42. }
  43. impl<T: 'static> CopyValue<T> {
  44. /// Create a new CopyValue. The value will be stored in the current component.
  45. ///
  46. /// Once the component this value is created in is dropped, the value will be dropped.
  47. pub fn new(value: T) -> Self {
  48. let owner = current_owner();
  49. Self {
  50. value: owner.insert(value),
  51. origin_scope: current_scope_id().expect("in a virtual dom"),
  52. }
  53. }
  54. /// Create a new CopyValue. The value will be stored in the given scope. When the specified scope is dropped, the value will be dropped.
  55. pub fn new_in_scope(value: T, scope: ScopeId) -> Self {
  56. let owner = owner_in_scope(scope);
  57. Self {
  58. value: owner.insert(value),
  59. origin_scope: scope,
  60. }
  61. }
  62. pub(crate) fn invalid() -> Self {
  63. let owner = current_owner();
  64. Self {
  65. value: owner.invalid(),
  66. origin_scope: current_scope_id().expect("in a virtual dom"),
  67. }
  68. }
  69. /// Get the scope this value was created in.
  70. pub fn origin_scope(&self) -> ScopeId {
  71. self.origin_scope
  72. }
  73. /// Try to read the value. If the value has been dropped, this will return None.
  74. pub fn try_read(&self) -> Option<Ref<'_, T>> {
  75. self.value.try_read()
  76. }
  77. /// Read the value. If the value has been dropped, this will panic.
  78. pub fn read(&self) -> Ref<'_, T> {
  79. self.value.read()
  80. }
  81. /// Try to write the value. If the value has been dropped, this will return None.
  82. pub fn try_write(&self) -> Option<RefMut<'_, T>> {
  83. self.value.try_write()
  84. }
  85. /// Write the value. If the value has been dropped, this will panic.
  86. pub fn write(&self) -> RefMut<'_, T> {
  87. self.value.write()
  88. }
  89. /// Set the value. If the value has been dropped, this will panic.
  90. pub fn set(&mut self, value: T) {
  91. *self.write() = value;
  92. }
  93. /// Run a function with a reference to the value. If the value has been dropped, this will panic.
  94. pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
  95. let write = self.read();
  96. f(&*write)
  97. }
  98. /// Run a function with a mutable reference to the value. If the value has been dropped, this will panic.
  99. pub fn with_mut<O>(&self, f: impl FnOnce(&mut T) -> O) -> O {
  100. let mut write = self.write();
  101. f(&mut *write)
  102. }
  103. }
  104. impl<T: Clone + 'static> CopyValue<T> {
  105. /// Get the value. If the value has been dropped, this will panic.
  106. pub fn value(&self) -> T {
  107. self.read().clone()
  108. }
  109. }
  110. impl<T: 'static> PartialEq for CopyValue<T> {
  111. fn eq(&self, other: &Self) -> bool {
  112. self.value.ptr_eq(&other.value)
  113. }
  114. }