From 6a3c50a965167078c131b24bd87d6513c1d6537e Mon Sep 17 00:00:00 2001 From: zach Date: Thu, 27 Jun 2024 15:23:55 -0700 Subject: [PATCH] cleanup: return no results from generated shared_fn when the result is `SharedFnResult<()>` (#58) * cleanup: return no results from shared_fn when the result is SharedFnResult<()> * fix: shared_fn example --- derive/src/lib.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 77f47b4..5017d10 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -1,6 +1,6 @@ use proc_macro2::{Ident, Span}; use quote::quote; -use syn::{parse_macro_input, FnArg, ItemFn, ItemForeignMod}; +use syn::{parse_macro_input, FnArg, GenericArgument, ItemFn, ItemForeignMod, PathArguments}; /// `plugin_fn` is used to define an Extism callable function to export /// @@ -122,13 +122,13 @@ pub fn plugin_fn( /// `extern "C" fn` should be used instead. /// /// All arguments should implement `extism_pdk::ToBytes` and the return value should implement -/// `extism_pdk::FromBytes` +/// `extism_pdk::FromBytes`, if `()` or `SharedFnResult<()>` then no value will be returned. /// ## Example /// /// ```rust -/// use extism_pdk::{FnResult, shared_fn}; +/// use extism_pdk::{SharedFnResult, shared_fn}; /// #[shared_fn] -/// pub fn greet2(greeting: String, name: String) -> FnResult { +/// pub fn greet2(greeting: String, name: String) -> SharedFnResult { /// let s = format!("{greeting}, {name}"); /// Ok(name) /// } @@ -179,16 +179,36 @@ pub fn shared_fn( let (no_result, raw_output) = match output { syn::ReturnType::Default => (true, quote! {}), syn::ReturnType::Type(_, t) => { + let mut is_unit = false; if let syn::Type::Path(p) = t.as_ref() { if let Some(t) = p.path.segments.last() { if t.ident != "SharedFnResult" { panic!("extism_pdk::shared_fn expects a function that returns extism_pdk::SharedFnResult"); } + match &t.arguments { + PathArguments::AngleBracketed(args) => { + if args.args.len() == 1 { + match &args.args[0] { + GenericArgument::Type(syn::Type::Tuple(t)) => { + if t.elems.is_empty() { + is_unit = true; + } + } + _ => (), + } + } + } + _ => (), + } } else { panic!("extism_pdk::shared_fn expects a function that returns extism_pdk::SharedFnResult"); } }; - (false, quote! {-> u64 }) + if is_unit { + (true, quote! {}) + } else { + (false, quote! {-> u64 }) + } } };