summaryrefslogtreecommitdiff
path: root/ops/lib.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-11-26 06:37:43 -0800
committerGitHub <noreply@github.com>2022-11-26 20:07:43 +0530
commitfcdcc8c0c3316857e327bb3c0109fd244f1ec409 (patch)
tree136b98ac68990e8c38aa561b3ff13126ac53dc8e /ops/lib.rs
parent7e0c55818721b78109e2bb58bf14f814036bf06d (diff)
feat(ops): support raw pointer arguments (#16826)
See https://github.com/denoland/deno/pull/16814#discussion_r1032744083. Allows nullable buffers in low-level ops like FFI: ```rust fn op_ffi_ptr_of<FP>( state: &mut OpState, buf: *const u8, out: &mut [u32], ) where FP: FfiPermissions + 'static { // .. } ```
Diffstat (limited to 'ops/lib.rs')
-rw-r--r--ops/lib.rs36
1 files changed, 35 insertions, 1 deletions
diff --git a/ops/lib.rs b/ops/lib.rs
index efd47f8e5..6b57e1cd9 100644
--- a/ops/lib.rs
+++ b/ops/lib.rs
@@ -432,6 +432,13 @@ fn codegen_arg(
};
}
}
+ // Fast path for `*const u8`
+ if is_ptr_u8(&**ty) {
+ let blk = codegen_u8_ptr(core, idx);
+ return quote! {
+ let #ident = #blk;
+ };
+ }
// Otherwise deserialize it via serde_v8
quote! {
let #ident = args.get(#idx as i32);
@@ -450,7 +457,6 @@ fn codegen_u8_slice(core: &TokenStream2, idx: usize) -> TokenStream2 {
let value = args.get(#idx as i32);
match #core::v8::Local::<#core::v8::ArrayBuffer>::try_from(value) {
Ok(b) => {
- // Handles detached buffers.
let byte_length = b.byte_length();
let store = b.data() as *mut u8;
// SAFETY: rust guarantees that lifetime of slice is no longer than the call.
@@ -477,6 +483,30 @@ fn codegen_u8_slice(core: &TokenStream2, idx: usize) -> TokenStream2 {
}
}
+fn codegen_u8_ptr(core: &TokenStream2, idx: usize) -> TokenStream2 {
+ quote! {{
+ let value = args.get(#idx as i32);
+ match #core::v8::Local::<#core::v8::ArrayBuffer>::try_from(value) {
+ Ok(b) => b.data() as *const u8,
+ Err(_) => {
+ if let Ok(view) = #core::v8::Local::<#core::v8::ArrayBufferView>::try_from(value) {
+ let offset = view.byte_offset();
+ let buffer = match view.buffer(scope) {
+ Some(v) => v,
+ None => {
+ return #core::_ops::throw_type_error(scope, format!("Expected ArrayBufferView at position {}", #idx));
+ }
+ };
+ let store = buffer.data() as *mut u8;
+ unsafe { store.add(offset) }
+ } else {
+ return #core::_ops::throw_type_error(scope, format!("Expected ArrayBufferView at position {}", #idx));
+ }
+ }
+ }
+ }}
+}
+
fn codegen_u32_mut_slice(core: &TokenStream2, idx: usize) -> TokenStream2 {
quote! {
if let Ok(view) = #core::v8::Local::<#core::v8::Uint32Array>::try_from(args.get(#idx as i32)) {
@@ -602,6 +632,10 @@ fn is_u32_slice_mut(ty: impl ToTokens) -> bool {
tokens(ty) == "& mut [u32]"
}
+fn is_ptr_u8(ty: impl ToTokens) -> bool {
+ tokens(ty) == "* const u8"
+}
+
fn is_optional_fast_callback_option(ty: impl ToTokens) -> bool {
tokens(&ty).contains("Option < & mut FastApiCallbackOptions")
}