MCPcopy Create free account
hub / github.com/dylan-sutton-chavez/edge-python / plugin_methods

Function plugin_methods

wasm-pdk/macros/src/lib.rs:215–288  ·  view source on GitHub ↗
(_attr: TokenStream, item: TokenStream)

Source from the content-addressed store, hash-verified

213
214#[proc_macro_attribute]
215pub fn plugin_methods(_attr: TokenStream, item: TokenStream) -> TokenStream {
216 let input = parse_macro_input!(item as ItemImpl);
217 let self_ty = match &*input.self_ty {
218 Type::Path(p) => p.path.segments.last().expect("plugin_methods: empty path").ident.clone(),
219 _ => return quote! { compile_error!("#[plugin_methods] requires a simple type path"); }.into(),
220 };
221 let class_name = self_ty.to_string();
222
223 let mut emitted: Vec<TokenStream2> = Vec::new();
224
225 for item in &input.items {
226 let ImplItem::Fn(method) = item else { continue; };
227 let is_ctor = method.attrs.iter().any(|a| a.path().is_ident("plugin_ctor"));
228 let method_name = method.sig.ident.to_string();
229 let method_ident = &method.sig.ident;
230
231 if is_ctor {
232 let export_ident = format_ident!("__class_{}___init__", class_name);
233 emitted.push(quote! {
234 #[::wasm_pdk::plugin_fn]
235 fn #export_ident(self_h: ::wasm_pdk::Handle) -> ::wasm_pdk::Result<()> {
236 let instance = #self_ty::#method_ident();
237 let id = #self_ty::__edge_insert(instance);
238 let id_handle = <i64 as ::wasm_pdk::IntoValue>::into_handle(id)?;
239 self_h.set_attr("__rust_id", &id_handle)?;
240 Ok(())
241 }
242 });
243 continue;
244 }
245
246 let export_ident = format_ident!("__class_{}_{}", class_name, method_name);
247 let user_args: Vec<_> = method.sig.inputs.iter().skip(1).collect();
248 let user_arg_names: Vec<_> = user_args.iter().filter_map(|a| match a {
249 FnArg::Typed(pt) => match &*pt.pat { Pat::Ident(id) => Some(id.ident.clone()), _ => None },
250 _ => None,
251 }).collect();
252 let user_arg_types: Vec<_> = user_args.iter().filter_map(|a| match a {
253 FnArg::Typed(pt) => Some((*pt.ty).clone()),
254 _ => None,
255 }).collect();
256 let user_ret_ty: syn::Type = match &method.sig.output {
257 ReturnType::Default => syn::parse_quote!(()),
258 ReturnType::Type(_, t) => (**t).clone(),
259 };
260 // Detect if user method already returns Result; avoids generating Result<Result<T>>.
261 let is_user_result = matches!(&user_ret_ty, Type::Path(p)
262 if p.path.segments.last().map(|s| s.ident == "Result").unwrap_or(false));
263 let (wrapper_ret, call_expr) = if is_user_result {
264 (quote! { #user_ret_ty },
265 quote! { instance.#method_ident(#(#user_arg_names),*) })
266 } else {
267 (quote! { ::wasm_pdk::Result<#user_ret_ty> },
268 quote! { Ok(instance.#method_ident(#(#user_arg_names),*)) })
269 };
270
271 emitted.push(quote! {
272 #[::wasm_pdk::plugin_fn]

Callers

nothing calls this directly

Calls 4

pushMethod · 0.80
collectMethod · 0.80
expectMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected