mod.rs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. //! The Tauri custom commands types and traits.
  5. //!
  6. //! You usually don't need to create these items yourself. These are created from [command](../attr.command.html)
  7. //! attribute macro along the way and used by [`crate::generate_handler`] macro.
  8. use crate::{
  9. ipc::{InvokeBody, InvokeError, InvokeMessage},
  10. Runtime,
  11. };
  12. use serde::{
  13. de::{Error, Visitor},
  14. Deserialize, Deserializer,
  15. };
  16. mod authority;
  17. pub use authority::{CommandScope, GlobalScope, Origin, RuntimeAuthority, ScopeObject, ScopeValue};
  18. use tauri_utils::acl::resolved::ResolvedCommand;
  19. /// Represents a custom command.
  20. pub struct CommandItem<'a, R: Runtime> {
  21. /// Name of the plugin if this command targets one.
  22. pub plugin: Option<&'static str>,
  23. /// The name of the command, e.g. `handler` on `#[command] fn handler(value: u64)`
  24. pub name: &'static str,
  25. /// The key of the command item, e.g. `value` on `#[command] fn handler(value: u64)`
  26. pub key: &'static str,
  27. /// The [`InvokeMessage`] that was passed to this command.
  28. pub message: &'a InvokeMessage<R>,
  29. /// The resolved ACL for this command.
  30. pub acl: &'a Option<ResolvedCommand>,
  31. }
  32. /// Trait implemented by command arguments to derive a value from a [`CommandItem`].
  33. ///
  34. /// # Command Arguments
  35. ///
  36. /// A command argument is any type that represents an item parsable from a [`CommandItem`]. Most
  37. /// implementations will use the data stored in [`InvokeMessage`] since [`CommandItem`] is mostly a
  38. /// wrapper around it.
  39. ///
  40. /// # Provided Implementations
  41. ///
  42. /// Tauri implements [`CommandArg`] automatically for a number of types.
  43. /// * [`crate::Window`]
  44. /// * [`crate::State`]
  45. /// * `T where T: serde::Deserialize`
  46. /// * Any type that implements `Deserialize` can automatically be used as a [`CommandArg`].
  47. pub trait CommandArg<'de, R: Runtime>: Sized {
  48. /// Derives an instance of `Self` from the [`CommandItem`].
  49. ///
  50. /// If the derivation fails, the corresponding message will be rejected using [`InvokeMessage#reject`].
  51. fn from_command(command: CommandItem<'de, R>) -> Result<Self, InvokeError>;
  52. }
  53. /// Automatically implement [`CommandArg`] for any type that can be deserialized.
  54. impl<'de, D: Deserialize<'de>, R: Runtime> CommandArg<'de, R> for D {
  55. fn from_command(command: CommandItem<'de, R>) -> Result<D, InvokeError> {
  56. let name = command.name;
  57. let arg = command.key;
  58. #[cfg(feature = "tracing")]
  59. let _span = tracing::trace_span!("ipc::request::deserialize_arg", arg = arg).entered();
  60. Self::deserialize(command).map_err(|e| crate::Error::InvalidArgs(name, arg, e).into())
  61. }
  62. }
  63. /// Pass the result of [`serde_json::Value::get`] into [`serde_json::Value`]'s deserializer.
  64. ///
  65. /// Returns an error if the [`CommandItem`]'s key does not exist in the value.
  66. macro_rules! pass {
  67. ($fn:ident, $($arg:ident: $argt:ty),+) => {
  68. fn $fn<V: Visitor<'de>>(self, $($arg: $argt),*) -> Result<V::Value, Self::Error> {
  69. if self.key.is_empty() {
  70. return Err(serde_json::Error::custom(format!(
  71. "command {} has an argument with no name with a non-optional value",
  72. self.name
  73. )))
  74. }
  75. match &self.message.payload {
  76. InvokeBody::Raw(_body) => {
  77. Err(serde_json::Error::custom(format!(
  78. "command {} expected a value for key {} but the IPC call used a bytes payload",
  79. self.name, self.key
  80. )))
  81. }
  82. InvokeBody::Json(v) => {
  83. match v.get(self.key) {
  84. Some(value) => value.$fn($($arg),*),
  85. None => {
  86. Err(serde_json::Error::custom(format!(
  87. "command {} missing required key {}",
  88. self.name, self.key
  89. )))
  90. }
  91. }
  92. }
  93. }
  94. }
  95. }
  96. }
  97. /// A [`Deserializer`] wrapper around [`CommandItem`].
  98. ///
  99. /// If the key doesn't exist, an error will be returned if the deserialized type is not expecting
  100. /// an optional item. If the key does exist, the value will be called with
  101. /// [`Value`](serde_json::Value)'s [`Deserializer`] implementation.
  102. impl<'de, R: Runtime> Deserializer<'de> for CommandItem<'de, R> {
  103. type Error = serde_json::Error;
  104. pass!(deserialize_any, visitor: V);
  105. pass!(deserialize_bool, visitor: V);
  106. pass!(deserialize_i8, visitor: V);
  107. pass!(deserialize_i16, visitor: V);
  108. pass!(deserialize_i32, visitor: V);
  109. pass!(deserialize_i64, visitor: V);
  110. pass!(deserialize_u8, visitor: V);
  111. pass!(deserialize_u16, visitor: V);
  112. pass!(deserialize_u32, visitor: V);
  113. pass!(deserialize_u64, visitor: V);
  114. pass!(deserialize_f32, visitor: V);
  115. pass!(deserialize_f64, visitor: V);
  116. pass!(deserialize_char, visitor: V);
  117. pass!(deserialize_str, visitor: V);
  118. pass!(deserialize_string, visitor: V);
  119. pass!(deserialize_bytes, visitor: V);
  120. pass!(deserialize_byte_buf, visitor: V);
  121. fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
  122. match &self.message.payload {
  123. InvokeBody::Raw(_body) => Err(serde_json::Error::custom(format!(
  124. "command {} expected a value for key {} but the IPC call used a bytes payload",
  125. self.name, self.key
  126. ))),
  127. InvokeBody::Json(v) => match v.get(self.key) {
  128. Some(value) => value.deserialize_option(visitor),
  129. None => visitor.visit_none(),
  130. },
  131. }
  132. }
  133. pass!(deserialize_unit, visitor: V);
  134. pass!(deserialize_unit_struct, name: &'static str, visitor: V);
  135. pass!(deserialize_newtype_struct, name: &'static str, visitor: V);
  136. pass!(deserialize_seq, visitor: V);
  137. pass!(deserialize_tuple, len: usize, visitor: V);
  138. pass!(
  139. deserialize_tuple_struct,
  140. name: &'static str,
  141. len: usize,
  142. visitor: V
  143. );
  144. pass!(deserialize_map, visitor: V);
  145. pass!(
  146. deserialize_struct,
  147. name: &'static str,
  148. fields: &'static [&'static str],
  149. visitor: V
  150. );
  151. pass!(
  152. deserialize_enum,
  153. name: &'static str,
  154. fields: &'static [&'static str],
  155. visitor: V
  156. );
  157. pass!(deserialize_identifier, visitor: V);
  158. pass!(deserialize_ignored_any, visitor: V);
  159. }
  160. /// [Autoref-based stable specialization](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md)
  161. ///
  162. /// Nothing in this module is considered stable.
  163. #[doc(hidden)]
  164. pub mod private {
  165. use crate::{
  166. ipc::{InvokeBody, InvokeError, InvokeResolver, IpcResponse},
  167. Runtime,
  168. };
  169. use futures_util::{FutureExt, TryFutureExt};
  170. use std::future::Future;
  171. #[cfg(feature = "tracing")]
  172. pub use tracing;
  173. // ===== impl IpcResponse =====
  174. pub struct ResponseTag;
  175. pub trait ResponseKind {
  176. #[inline(always)]
  177. fn blocking_kind(&self) -> ResponseTag {
  178. ResponseTag
  179. }
  180. #[inline(always)]
  181. fn async_kind(&self) -> ResponseTag {
  182. ResponseTag
  183. }
  184. }
  185. impl<T: IpcResponse> ResponseKind for &T {}
  186. impl ResponseTag {
  187. #[inline(always)]
  188. pub fn block<R, T>(self, value: T, resolver: InvokeResolver<R>)
  189. where
  190. R: Runtime,
  191. T: IpcResponse,
  192. {
  193. resolver.respond(Ok(value))
  194. }
  195. #[inline(always)]
  196. pub fn future<T>(self, value: T) -> impl Future<Output = Result<InvokeBody, InvokeError>>
  197. where
  198. T: IpcResponse,
  199. {
  200. std::future::ready(value.body().map_err(InvokeError::from_error))
  201. }
  202. }
  203. // ===== Result<impl Serialize, impl Into<InvokeError>> =====
  204. pub struct ResultTag;
  205. pub trait ResultKind {
  206. #[inline(always)]
  207. fn blocking_kind(&self) -> ResultTag {
  208. ResultTag
  209. }
  210. #[inline(always)]
  211. fn async_kind(&self) -> ResultTag {
  212. ResultTag
  213. }
  214. }
  215. impl<T: IpcResponse, E: Into<InvokeError>> ResultKind for Result<T, E> {}
  216. impl ResultTag {
  217. #[inline(always)]
  218. pub fn block<R, T, E>(self, value: Result<T, E>, resolver: InvokeResolver<R>)
  219. where
  220. R: Runtime,
  221. T: IpcResponse,
  222. E: Into<InvokeError>,
  223. {
  224. resolver.respond(value.map_err(Into::into))
  225. }
  226. #[inline(always)]
  227. pub fn future<T, E>(
  228. self,
  229. value: Result<T, E>,
  230. ) -> impl Future<Output = Result<InvokeBody, InvokeError>>
  231. where
  232. T: IpcResponse,
  233. E: Into<InvokeError>,
  234. {
  235. std::future::ready(
  236. value
  237. .map_err(Into::into)
  238. .and_then(|value| value.body().map_err(InvokeError::from_error)),
  239. )
  240. }
  241. }
  242. // ===== Future<Output = impl IpcResponse> =====
  243. pub struct FutureTag;
  244. pub trait FutureKind {
  245. #[inline(always)]
  246. fn async_kind(&self) -> FutureTag {
  247. FutureTag
  248. }
  249. }
  250. impl<T: IpcResponse, F: Future<Output = T>> FutureKind for &F {}
  251. impl FutureTag {
  252. #[inline(always)]
  253. pub fn future<T, F>(self, value: F) -> impl Future<Output = Result<InvokeBody, InvokeError>>
  254. where
  255. T: IpcResponse,
  256. F: Future<Output = T> + Send + 'static,
  257. {
  258. value.map(|value| value.body().map_err(InvokeError::from_error))
  259. }
  260. }
  261. // ===== Future<Output = Result<impl Serialize, impl Into<InvokeError>>> =====
  262. pub struct ResultFutureTag;
  263. pub trait ResultFutureKind {
  264. #[inline(always)]
  265. fn async_kind(&self) -> ResultFutureTag {
  266. ResultFutureTag
  267. }
  268. }
  269. impl<T: IpcResponse, E: Into<InvokeError>, F: Future<Output = Result<T, E>>> ResultFutureKind
  270. for F
  271. {
  272. }
  273. impl ResultFutureTag {
  274. #[inline(always)]
  275. pub fn future<T, E, F>(self, value: F) -> impl Future<Output = Result<InvokeBody, InvokeError>>
  276. where
  277. T: IpcResponse,
  278. E: Into<InvokeError>,
  279. F: Future<Output = Result<T, E>> + Send,
  280. {
  281. value
  282. .err_into()
  283. .map(|result| result.and_then(|value| value.body().map_err(InvokeError::from_error)))
  284. }
  285. }
  286. }