mod.rs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
  2. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  3. // SPDX-License-Identifier: Apache-2.0
  4. // SPDX-License-Identifier: MIT
  5. // a modified version of https://github.com/denoland/deno/blob/0ae83847f498a2886ae32172e50fd5bdbab2f524/core/resources.rs#L220
  6. pub(crate) mod plugin;
  7. use crate::error::Error;
  8. use std::{
  9. any::{type_name, Any, TypeId},
  10. borrow::Cow,
  11. collections::BTreeMap,
  12. sync::Arc,
  13. };
  14. /// Resources are Rust objects that are stored in [ResourceTable] and managed by tauri.
  15. /// They are identified in JS by a numeric ID (the resource ID, or rid).
  16. /// Resources can be created in commands. Resources can also be retrieved in commands by
  17. /// their rid. Resources are thread-safe.
  18. ///
  19. /// Resources are reference counted in Rust. This means that they can be
  20. /// cloned and passed around. When the last reference is dropped, the resource
  21. /// is automatically closed. As long as the resource exists in the resource
  22. /// table, the reference count is at least 1.
  23. pub trait Resource: Any + 'static + Send + Sync {
  24. /// Returns a string representation of the resource. The default implementation
  25. /// returns the Rust type name, but specific resource types may override this
  26. /// trait method.
  27. fn name(&self) -> Cow<'_, str> {
  28. type_name::<Self>().into()
  29. }
  30. /// Resources may implement the `close()` trait method if they need to do
  31. /// resource specific clean-ups, such as cancelling pending futures, after a
  32. /// resource has been removed from the resource table.
  33. fn close(self: Arc<Self>) {}
  34. }
  35. impl dyn Resource {
  36. #[inline(always)]
  37. fn is<T: Resource>(&self) -> bool {
  38. self.type_id() == TypeId::of::<T>()
  39. }
  40. #[inline(always)]
  41. pub(crate) fn downcast_arc<'a, T: Resource>(self: &'a Arc<Self>) -> Option<&'a Arc<T>> {
  42. if self.is::<T>() {
  43. // A resource is stored as `Arc<T>` in a BTreeMap
  44. // and is safe to cast to `Arc<T>` because of the runtime
  45. // check done in `self.is::<T>()`
  46. let ptr = self as *const Arc<_> as *const Arc<T>;
  47. Some(unsafe { &*ptr })
  48. } else {
  49. None
  50. }
  51. }
  52. }
  53. /// A `ResourceId` is an integer value referencing a resource. It could be
  54. /// considered to be the tauri equivalent of a `file descriptor` in POSIX like
  55. /// operating systems.
  56. pub type ResourceId = u32;
  57. /// Map-like data structure storing Tauri's resources (equivalent to file
  58. /// descriptors).
  59. ///
  60. /// Provides basic methods for element access. A resource can be of any type.
  61. /// Different types of resources can be stored in the same map, and provided
  62. /// with a name for description.
  63. ///
  64. /// Each resource is identified through a _resource ID (rid)_, which acts as
  65. /// the key in the map.
  66. #[derive(Default)]
  67. pub struct ResourceTable {
  68. index: BTreeMap<ResourceId, Arc<dyn Resource>>,
  69. next_rid: ResourceId,
  70. }
  71. impl ResourceTable {
  72. /// Inserts resource into the resource table, which takes ownership of it.
  73. ///
  74. /// The resource type is erased at runtime and must be statically known
  75. /// when retrieving it through `get()`.
  76. ///
  77. /// Returns a unique resource ID, which acts as a key for this resource.
  78. pub fn add<T: Resource>(&mut self, resource: T) -> ResourceId {
  79. self.add_arc(Arc::new(resource))
  80. }
  81. /// Inserts a `Arc`-wrapped resource into the resource table.
  82. ///
  83. /// The resource type is erased at runtime and must be statically known
  84. /// when retrieving it through `get()`.
  85. ///
  86. /// Returns a unique resource ID, which acts as a key for this resource.
  87. pub fn add_arc<T: Resource>(&mut self, resource: Arc<T>) -> ResourceId {
  88. let resource = resource as Arc<dyn Resource>;
  89. self.add_arc_dyn(resource)
  90. }
  91. /// Inserts a `Arc`-wrapped resource into the resource table.
  92. ///
  93. /// The resource type is erased at runtime and must be statically known
  94. /// when retrieving it through `get()`.
  95. ///
  96. /// Returns a unique resource ID, which acts as a key for this resource.
  97. pub fn add_arc_dyn(&mut self, resource: Arc<dyn Resource>) -> ResourceId {
  98. let rid = self.next_rid;
  99. let removed_resource = self.index.insert(rid, resource);
  100. assert!(removed_resource.is_none());
  101. self.next_rid += 1;
  102. rid
  103. }
  104. /// Returns true if any resource with the given `rid` exists.
  105. pub fn has(&self, rid: ResourceId) -> bool {
  106. self.index.contains_key(&rid)
  107. }
  108. /// Returns a reference counted pointer to the resource of type `T` with the
  109. /// given `rid`. If `rid` is not present or has a type different than `T`,
  110. /// this function returns [`Error::BadResourceId`].
  111. pub fn get<T: Resource>(&self, rid: ResourceId) -> Result<Arc<T>, Error> {
  112. self
  113. .index
  114. .get(&rid)
  115. .and_then(|rc| rc.downcast_arc::<T>())
  116. .map(Clone::clone)
  117. .ok_or_else(|| Error::BadResourceId(rid))
  118. }
  119. /// Returns a reference counted pointer to the resource of the given `rid`.
  120. /// If `rid` is not present, this function returns [`Error::BadResourceId`].
  121. pub fn get_any(&self, rid: ResourceId) -> Result<Arc<dyn Resource>, Error> {
  122. self
  123. .index
  124. .get(&rid)
  125. .map(Clone::clone)
  126. .ok_or_else(|| Error::BadResourceId(rid))
  127. }
  128. /// Replaces a resource with a new resource.
  129. ///
  130. /// Panics if the resource does not exist.
  131. pub fn replace<T: Resource>(&mut self, rid: ResourceId, resource: T) {
  132. let result = self
  133. .index
  134. .insert(rid, Arc::new(resource) as Arc<dyn Resource>);
  135. assert!(result.is_some());
  136. }
  137. /// Removes a resource of type `T` from the resource table and returns it.
  138. /// If a resource with the given `rid` exists but its type does not match `T`,
  139. /// it is not removed from the resource table. Note that the resource's
  140. /// `close()` method is *not* called.
  141. ///
  142. /// Also note that there might be a case where
  143. /// the returned `Arc<T>` is referenced by other variables. That is, we cannot
  144. /// assume that `Arc::strong_count(&returned_arc)` is always equal to 1 on success.
  145. /// In particular, be really careful when you want to extract the inner value of
  146. /// type `T` from `Arc<T>`.
  147. pub fn take<T: Resource>(&mut self, rid: ResourceId) -> Result<Arc<T>, Error> {
  148. let resource = self.get::<T>(rid)?;
  149. self.index.remove(&rid);
  150. Ok(resource)
  151. }
  152. /// Removes a resource from the resource table and returns it. Note that the
  153. /// resource's `close()` method is *not* called.
  154. ///
  155. /// Also note that there might be a
  156. /// case where the returned `Arc<T>` is referenced by other variables. That is,
  157. /// we cannot assume that `Arc::strong_count(&returned_arc)` is always equal to 1
  158. /// on success. In particular, be really careful when you want to extract the
  159. /// inner value of type `T` from `Arc<T>`.
  160. pub fn take_any(&mut self, rid: ResourceId) -> Result<Arc<dyn Resource>, Error> {
  161. self
  162. .index
  163. .remove(&rid)
  164. .ok_or_else(|| Error::BadResourceId(rid))
  165. }
  166. /// Returns an iterator that yields a `(id, name)` pair for every resource
  167. /// that's currently in the resource table. This can be used for debugging
  168. /// purposes. Note that the order in
  169. /// which items appear is not specified.
  170. pub fn names(&self) -> impl Iterator<Item = (ResourceId, Cow<'_, str>)> {
  171. self
  172. .index
  173. .iter()
  174. .map(|(&id, resource)| (id, resource.name()))
  175. }
  176. /// Removes the resource with the given `rid` from the resource table. If the
  177. /// only reference to this resource existed in the resource table, this will
  178. /// cause the resource to be dropped. However, since resources are reference
  179. /// counted, therefore pending ops are not automatically cancelled. A resource
  180. /// may implement the `close()` method to perform clean-ups such as canceling
  181. /// ops.
  182. pub fn close(&mut self, rid: ResourceId) -> Result<(), Error> {
  183. self
  184. .index
  185. .remove(&rid)
  186. .ok_or_else(|| Error::BadResourceId(rid))
  187. .map(|resource| resource.close())
  188. }
  189. /// Removes and frees all resources stored. Note that the
  190. /// resource's `close()` method is *not* called.
  191. pub(crate) fn clear(&mut self) {
  192. self.index.clear()
  193. }
  194. }