2023-01-02 16:00:42 -05:00
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2022-12-12 09:14:20 -05:00
use crate ::check_unstable ;
use crate ::FfiPermissions ;
use deno_core ::error ::range_error ;
use deno_core ::error ::type_error ;
use deno_core ::error ::AnyError ;
use deno_core ::op ;
use deno_core ::serde_v8 ;
use deno_core ::v8 ;
2023-02-28 01:26:48 -05:00
use deno_core ::OpState ;
2022-12-12 09:14:20 -05:00
use std ::ffi ::c_char ;
use std ::ffi ::c_void ;
use std ::ffi ::CStr ;
use std ::ptr ;
2023-02-22 12:32:38 -05:00
#[ op(fast) ]
fn op_ffi_ptr_create < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr_number : usize ,
) -> Result < * mut c_void , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointer#create " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
Ok ( ptr_number as * mut c_void )
}
#[ op(fast) ]
pub fn op_ffi_ptr_equals < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
a : * const c_void ,
b : * const c_void ,
) -> Result < bool , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointer#equals " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
Ok ( a = = b )
}
2022-12-12 09:14:20 -05:00
#[ op(fast) ]
pub fn op_ffi_ptr_of < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2022-12-12 09:14:20 -05:00
buf : * const u8 ,
2023-02-22 12:32:38 -05:00
) -> Result < * mut c_void , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointer#of " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
Ok ( buf as * mut c_void )
}
#[ op(fast) ]
fn op_ffi_ptr_offset < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
) -> Result < * mut c_void , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointer#offset " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid pointer to offset, pointer is null " ) ) ;
}
// SAFETY: Pointer and offset are user provided.
Ok ( unsafe { ptr . offset ( offset ) } )
}
unsafe extern " C " fn noop_deleter_callback (
_data : * mut c_void ,
_byte_length : usize ,
_deleter_data : * mut c_void ,
) {
}
#[ op(fast) ]
fn op_ffi_ptr_value < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
2022-12-12 09:14:20 -05:00
out : & mut [ u32 ] ,
) -> Result < ( ) , AnyError >
where
FP : FfiPermissions + 'static ,
{
2023-02-22 12:32:38 -05:00
check_unstable ( state , " Deno.UnsafePointer#value " ) ;
2022-12-12 09:14:20 -05:00
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
let outptr = out . as_ptr ( ) as * mut usize ;
let length = out . len ( ) ;
assert! (
length > = ( std ::mem ::size_of ::< usize > ( ) / std ::mem ::size_of ::< u32 > ( ) )
) ;
assert_eq! ( outptr as usize % std ::mem ::size_of ::< usize > ( ) , 0 ) ;
// SAFETY: Out buffer was asserted to be at least large enough to hold a usize, and properly aligned.
let out = unsafe { & mut * outptr } ;
2023-02-22 12:32:38 -05:00
* out = ptr as usize ;
2022-12-12 09:14:20 -05:00
Ok ( ( ) )
}
#[ op(v8) ]
pub fn op_ffi_get_buf < FP , ' scope > (
scope : & mut v8 ::HandleScope < ' scope > ,
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
len : usize ,
) -> Result < serde_v8 ::Value < ' scope > , AnyError >
where
FP : FfiPermissions + 'static ,
{
2023-02-22 12:32:38 -05:00
check_unstable ( state , " Deno.UnsafePointerView#getArrayBuffer " ) ;
2022-12-12 09:14:20 -05:00
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
2023-02-22 12:32:38 -05:00
return Err ( type_error ( " Invalid ArrayBuffer pointer, pointer is null " ) ) ;
2022-12-12 09:14:20 -05:00
}
2023-02-22 12:32:38 -05:00
// SAFETY: Trust the user to have provided a real pointer, offset, and a valid matching size to it. Since this is a foreign pointer, we should not do any deletion.
2022-12-12 09:14:20 -05:00
let backing_store = unsafe {
v8 ::ArrayBuffer ::new_backing_store_from_ptr (
2023-02-22 12:32:38 -05:00
ptr . offset ( offset ) ,
2022-12-12 09:14:20 -05:00
len ,
noop_deleter_callback ,
std ::ptr ::null_mut ( ) ,
)
}
. make_shared ( ) ;
let array_buffer : v8 ::Local < v8 ::Value > =
v8 ::ArrayBuffer ::with_backing_store ( scope , & backing_store ) . into ( ) ;
Ok ( array_buffer . into ( ) )
}
#[ op(fast) ]
pub fn op_ffi_buf_copy_into < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
src : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
dst : & mut [ u8 ] ,
len : usize ,
) -> Result < ( ) , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#copyInto " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
2023-02-22 12:32:38 -05:00
if src . is_null ( ) {
Err ( type_error ( " Invalid ArrayBuffer pointer, pointer is null " ) )
} else if dst . len ( ) < len {
2022-12-12 09:14:20 -05:00
Err ( range_error (
" Destination length is smaller than source length " ,
) )
} else {
let src = src as * const c_void ;
2023-02-22 12:32:38 -05:00
// SAFETY: src and offset are user defined.
2022-12-12 09:14:20 -05:00
// dest is properly aligned and is valid for writes of len * size_of::<T>() bytes.
2023-02-22 12:32:38 -05:00
unsafe {
ptr ::copy ::< u8 > ( src . offset ( offset ) as * const u8 , dst . as_mut_ptr ( ) , len )
} ;
2022-12-12 09:14:20 -05:00
Ok ( ( ) )
}
}
#[ op(v8) ]
pub fn op_ffi_cstr_read < FP , ' scope > (
scope : & mut v8 ::HandleScope < ' scope > ,
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < serde_v8 ::Value < ' scope > , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getCString " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid CString pointer, pointer is null " ) ) ;
}
2023-02-22 12:32:38 -05:00
let cstr =
// SAFETY: Pointer and offset are user provided.
unsafe { CStr ::from_ptr ( ptr . offset ( offset ) as * const c_char ) } . to_bytes ( ) ;
2023-02-12 11:42:35 -05:00
let value : v8 ::Local < v8 ::Value > =
v8 ::String ::new_from_utf8 ( scope , cstr , v8 ::NewStringType ::Normal )
. ok_or_else ( | | {
type_error ( " Invalid CString pointer, string exceeds max length " )
} ) ?
. into ( ) ;
2022-12-12 09:14:20 -05:00
Ok ( value . into ( ) )
}
#[ op(fast) ]
pub fn op_ffi_read_bool < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < bool , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getBool " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid bool pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
2023-02-22 12:32:38 -05:00
Ok ( unsafe { ptr ::read_unaligned ::< bool > ( ptr . offset ( offset ) as * const bool ) } )
2022-12-12 09:14:20 -05:00
}
#[ op(fast) ]
pub fn op_ffi_read_u8 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < u32 , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getUint8 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid u8 pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
2023-02-22 12:32:38 -05:00
Ok ( unsafe {
ptr ::read_unaligned ::< u8 > ( ptr . offset ( offset ) as * const u8 ) as u32
} )
2022-12-12 09:14:20 -05:00
}
#[ op(fast) ]
pub fn op_ffi_read_i8 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < i32 , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getInt8 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid i8 pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
2023-02-22 12:32:38 -05:00
Ok ( unsafe {
ptr ::read_unaligned ::< i8 > ( ptr . offset ( offset ) as * const i8 ) as i32
} )
2022-12-12 09:14:20 -05:00
}
#[ op(fast) ]
pub fn op_ffi_read_u16 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < u32 , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getUint16 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid u16 pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
Ok ( unsafe {
2023-02-22 12:32:38 -05:00
ptr ::read_unaligned ::< u16 > ( ptr . offset ( offset ) as * const u16 ) as u32
2022-12-12 09:14:20 -05:00
} )
}
#[ op(fast) ]
pub fn op_ffi_read_i16 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < i32 , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getInt16 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid i16 pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
Ok ( unsafe {
2023-02-22 12:32:38 -05:00
ptr ::read_unaligned ::< i16 > ( ptr . offset ( offset ) as * const i16 ) as i32
2022-12-12 09:14:20 -05:00
} )
}
#[ op(fast) ]
pub fn op_ffi_read_u32 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < u32 , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getUint32 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid u32 pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
2023-02-22 12:32:38 -05:00
Ok ( unsafe { ptr ::read_unaligned ::< u32 > ( ptr . offset ( offset ) as * const u32 ) } )
2022-12-12 09:14:20 -05:00
}
#[ op(fast) ]
pub fn op_ffi_read_i32 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < i32 , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getInt32 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid i32 pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
2023-02-22 12:32:38 -05:00
Ok ( unsafe { ptr ::read_unaligned ::< i32 > ( ptr . offset ( offset ) as * const i32 ) } )
2022-12-12 09:14:20 -05:00
}
#[ op ]
pub fn op_ffi_read_u64 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
out : & mut [ u32 ] ,
) -> Result < ( ) , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getBigUint64 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
let outptr = out . as_mut_ptr ( ) as * mut u64 ;
assert! (
out . len ( ) > = ( std ::mem ::size_of ::< u64 > ( ) / std ::mem ::size_of ::< u32 > ( ) )
) ;
assert_eq! ( ( outptr as usize % std ::mem ::size_of ::< u64 > ( ) ) , 0 ) ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid u64 pointer, pointer is null " ) ) ;
}
let value =
// SAFETY: ptr and offset are user provided.
2023-02-22 12:32:38 -05:00
unsafe { ptr ::read_unaligned ::< u64 > ( ptr . offset ( offset ) as * const u64 ) } ;
2022-12-12 09:14:20 -05:00
// SAFETY: Length and alignment of out slice were asserted to be correct.
unsafe { * outptr = value } ;
Ok ( ( ) )
}
#[ op(fast) ]
pub fn op_ffi_read_i64 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
out : & mut [ u32 ] ,
) -> Result < ( ) , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getBigUint64 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
let outptr = out . as_mut_ptr ( ) as * mut i64 ;
assert! (
out . len ( ) > = ( std ::mem ::size_of ::< i64 > ( ) / std ::mem ::size_of ::< u32 > ( ) )
) ;
assert_eq! ( ( outptr as usize % std ::mem ::size_of ::< i64 > ( ) ) , 0 ) ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid i64 pointer, pointer is null " ) ) ;
}
let value =
// SAFETY: ptr and offset are user provided.
2023-02-22 12:32:38 -05:00
unsafe { ptr ::read_unaligned ::< i64 > ( ptr . offset ( offset ) as * const i64 ) } ;
2022-12-12 09:14:20 -05:00
// SAFETY: Length and alignment of out slice were asserted to be correct.
unsafe { * outptr = value } ;
Ok ( ( ) )
}
#[ op(fast) ]
pub fn op_ffi_read_f32 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < f32 , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getFloat32 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid f32 pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
2023-02-22 12:32:38 -05:00
Ok ( unsafe { ptr ::read_unaligned ::< f32 > ( ptr . offset ( offset ) as * const f32 ) } )
2022-12-12 09:14:20 -05:00
}
#[ op(fast) ]
pub fn op_ffi_read_f64 < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
2022-12-12 09:14:20 -05:00
) -> Result < f64 , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getFloat64 " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid f64 pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
2023-02-22 12:32:38 -05:00
Ok ( unsafe { ptr ::read_unaligned ::< f64 > ( ptr . offset ( offset ) as * const f64 ) } )
}
#[ op(fast) ]
pub fn op_ffi_read_ptr < FP > (
2023-02-28 01:26:48 -05:00
state : & mut OpState ,
2023-02-22 12:32:38 -05:00
ptr : * mut c_void ,
offset : isize ,
) -> Result < * mut c_void , AnyError >
where
FP : FfiPermissions + 'static ,
{
check_unstable ( state , " Deno.UnsafePointerView#getPointer " ) ;
let permissions = state . borrow_mut ::< FP > ( ) ;
permissions . check ( None ) ? ;
if ptr . is_null ( ) {
return Err ( type_error ( " Invalid pointer pointer, pointer is null " ) ) ;
}
// SAFETY: ptr and offset are user provided.
Ok ( unsafe {
ptr ::read_unaligned ::< * mut c_void > ( ptr . offset ( offset ) as * const * mut c_void )
} )
2022-12-12 09:14:20 -05:00
}