handler.rs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Copyright 2019-2024 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use quote::format_ident;
  5. use syn::{
  6. parse::{Parse, ParseBuffer, ParseStream},
  7. Attribute, Ident, Path, Token,
  8. };
  9. struct CommandDef {
  10. path: Path,
  11. attrs: Vec<Attribute>,
  12. }
  13. impl Parse for CommandDef {
  14. fn parse(input: ParseStream) -> syn::Result<Self> {
  15. let attrs = input.call(Attribute::parse_outer)?;
  16. let path = input.parse()?;
  17. Ok(CommandDef { path, attrs })
  18. }
  19. }
  20. /// The items parsed from [`generate_handle!`](crate::generate_handle).
  21. pub struct Handler {
  22. command_defs: Vec<CommandDef>,
  23. commands: Vec<Ident>,
  24. wrappers: Vec<Path>,
  25. }
  26. impl Parse for Handler {
  27. fn parse(input: &ParseBuffer<'_>) -> syn::Result<Self> {
  28. let command_defs = input.parse_terminated(CommandDef::parse, Token![,])?;
  29. // parse the command names and wrappers from the passed paths
  30. let (commands, wrappers) = command_defs
  31. .iter()
  32. .map(|command_def| {
  33. let mut wrapper = command_def.path.clone();
  34. let last = super::path_to_command(&mut wrapper);
  35. // the name of the actual command function
  36. let command = last.ident.clone();
  37. // set the path to the command function wrapper
  38. last.ident = super::format_command_wrapper(&command);
  39. (command, wrapper)
  40. })
  41. .unzip();
  42. Ok(Self {
  43. command_defs: command_defs.into_iter().collect(), // remove punctuation separators
  44. commands,
  45. wrappers,
  46. })
  47. }
  48. }
  49. impl From<Handler> for proc_macro::TokenStream {
  50. fn from(
  51. Handler {
  52. command_defs,
  53. commands,
  54. wrappers,
  55. }: Handler,
  56. ) -> Self {
  57. let cmd = format_ident!("__tauri_cmd__");
  58. let invoke = format_ident!("__tauri_invoke__");
  59. let (paths, attrs): (Vec<Path>, Vec<Vec<Attribute>>) = command_defs
  60. .into_iter()
  61. .map(|def| (def.path, def.attrs))
  62. .unzip();
  63. quote::quote!(move |#invoke| {
  64. let #cmd = #invoke.message.command();
  65. match #cmd {
  66. #(#(#attrs)* stringify!(#commands) => #wrappers!(#paths, #invoke),)*
  67. _ => {
  68. return false;
  69. },
  70. }
  71. })
  72. .into()
  73. }
  74. }