diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2022-11-26 06:37:43 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-26 20:07:43 +0530 |
commit | fcdcc8c0c3316857e327bb3c0109fd244f1ec409 (patch) | |
tree | 136b98ac68990e8c38aa561b3ff13126ac53dc8e /ops/lib.rs | |
parent | 7e0c55818721b78109e2bb58bf14f814036bf06d (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.rs | 36 |
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") } |