diff options
author | Dr. Chat <arkolbed@gmail.com> | 2021-03-29 11:23:35 -0500 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2021-04-03 12:24:15 +0200 |
commit | c8c20a6c8bb759a162138673c809245821bcadf5 (patch) | |
tree | 3a7e231ed969754b889ba8050a1da28c46101025 | |
parent | 75eaaa6b61f896fe9fc788c4c21d27197c9ed2f6 (diff) |
Deduplicate dyngen code
-rw-r--r-- | src/codegen/dyngen.rs | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/src/codegen/dyngen.rs b/src/codegen/dyngen.rs index 59b8b3ca..f0152349 100644 --- a/src/codegen/dyngen.rs +++ b/src/codegen/dyngen.rs @@ -131,39 +131,41 @@ impl DynamicItems { assert_eq!(args.len(), args_identifiers.len()); } - self.struct_members.push( - if is_required { - quote! { - pub #ident: unsafe extern #abi fn ( #( #args),* ) #ret, - } - } else { - quote! { - pub #ident: Result<unsafe extern #abi fn ( #( #args ),* ) #ret, ::libloading::Error>, - } + let signature = quote! { unsafe extern #abi fn ( #( #args),* ) #ret }; + let member = if is_required { + signature + } else { + quote! { Result<#signature, ::libloading::Error> } + }; + + self.struct_members.push(quote! { + pub #ident: #member, + }); + + // N.B: If the signature was required, it won't be wrapped in a Result<...> + // and we can simply call it directly. + let call_body = if is_required { + quote! { + self.#ident(#( #args_identifiers ),*) + } + } else { + quote! { + let sym = self.#ident.as_ref().expect("Expected function, got error."); + (sym)(#( #args_identifiers ),*) } - ); + }; // We can't implement variadic functions from C easily, so we allow to // access the function pointer so that the user can call it just fine. if !is_variadic { - self.struct_implementation.push( - if is_required { - quote! { - pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty { - self.#ident(#( #args_identifiers ),*) - } - } - } else { - quote! { - pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty { - let sym = self.#ident.as_ref().expect("Expected function, got error."); - (sym)(#( #args_identifiers ),*) - } - } + self.struct_implementation.push(quote! { + pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty { + #call_body } - ); + }); } + // N.B: Unwrap the signature upon construction if it is required to be resolved. let ident_str = codegen::helpers::ast_ty::cstr_expr(ident.to_string()); self.constructor_inits.push(if is_required { quote! { |