command.rs 8.6 KB

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