summaryrefslogtreecommitdiff
path: root/ops/op2/mod.rs
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2023-06-29 10:23:14 -0600
committerGitHub <noreply@github.com>2023-06-29 10:23:14 -0600
commitfbb69329343c9985c26181e6297e6556c46d381d (patch)
treeee428c94727bdfdf9040a4944bd66981b4cd07fb /ops/op2/mod.rs
parent98df69fd4cbe3687e2ff3519fbd6bff4e5f3101f (diff)
refactor(ops): op2 support for generics (#19636)
Implementation of generics for `#[op2]`, along with some refactoring to improve the ergonomics of ops with generics parameters: - The ops have generics on the struct rather than the associated methods, which allows us to trait-ify ops (impossible when they are on the methods) - The decl() method can become a trait-associated const field which unlocks future optimizations Callers of ops need to switch from: `op_net_connect_tcp::call::<TestPermission>(conn_state, ip_addr)` to `op_net_connect_tcp::<TestPermission>::call(conn_state, ip_addr)`.
Diffstat (limited to 'ops/op2/mod.rs')
-rw-r--r--ops/op2/mod.rs38
1 files changed, 33 insertions, 5 deletions
diff --git a/ops/op2/mod.rs b/ops/op2/mod.rs
index 67a92d450..7f652fe1b 100644
--- a/ops/op2/mod.rs
+++ b/ops/op2/mod.rs
@@ -8,6 +8,7 @@ use quote::quote;
use quote::ToTokens;
use std::iter::zip;
use syn2::parse2;
+use syn2::parse_str;
use syn2::FnArg;
use syn2::ItemFn;
use syn2::Path;
@@ -104,6 +105,7 @@ fn generate_op2(
let call = Ident::new("call", Span::call_site());
let mut op_fn = func.clone();
op_fn.attrs.clear();
+ op_fn.sig.generics.params.clear();
op_fn.sig.ident = call.clone();
// Clear inert attributes
@@ -133,8 +135,8 @@ fn generate_op2(
let scope = Ident::new("scope", Span::call_site());
let info = Ident::new("info", Span::call_site());
let opctx = Ident::new("opctx", Span::call_site());
- let slow_function = Ident::new("slow_function", Span::call_site());
- let fast_function = Ident::new("fast_function", Span::call_site());
+ let slow_function = Ident::new("v8_fn_ptr", Span::call_site());
+ let fast_function = Ident::new("v8_fn_ptr_fast", Span::call_site());
let fast_api_callback_options =
Ident::new("fast_api_callback_options", Span::call_site());
@@ -196,13 +198,39 @@ fn generate_op2(
let arg_count: usize = generator_state.args.len();
let vis = func.vis;
+ let generic = signature
+ .generic_bounds
+ .keys()
+ .map(|s| format_ident!("{s}"))
+ .collect::<Vec<_>>();
+ let bound = signature
+ .generic_bounds
+ .values()
+ .map(|p| parse_str::<Path>(p).expect("Failed to reparse path"))
+ .collect::<Vec<_>>();
Ok(quote! {
#[allow(non_camel_case_types)]
- #vis struct #name {
+ #vis struct #name <#(#generic),*> {
+ // We need to mark these type parameters as used, so we use a PhantomData
+ _unconstructable: ::std::marker::PhantomData<(#(#generic),*)>
}
- impl #name {
+ impl <#(#generic : #bound),*> #deno_core::_ops::Op for #name <#(#generic),*> {
+ const NAME: &'static str = stringify!(#name);
+ const DECL: #deno_core::_ops::OpDecl = #deno_core::_ops::OpDecl {
+ name: stringify!(#name),
+ v8_fn_ptr: Self::#slow_function as _,
+ enabled: true,
+ fast_fn: #fast_definition,
+ is_async: false,
+ is_unstable: false,
+ is_v8: false,
+ arg_count: #arg_count as u8,
+ };
+ }
+
+ impl <#(#generic : #bound),*> #name <#(#generic),*> {
pub const fn name() -> &'static str {
stringify!(#name)
}
@@ -220,8 +248,8 @@ fn generate_op2(
}
}
- #slow_fn
#fast_fn
+ #slow_fn
#[inline(always)]
#op_fn