// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use crate::dlfcn::DynamicLibraryResource; use crate::symbol::NativeType; use crate::MAX_SAFE_INTEGER; use crate::MIN_SAFE_INTEGER; use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::op; use deno_core::serde_v8; use deno_core::v8; use deno_core::ResourceId; use std::ffi::c_void; use std::ptr; #[op(v8)] pub fn op_ffi_get_static<'scope>( scope: &mut v8::HandleScope<'scope>, state: &mut deno_core::OpState, rid: ResourceId, name: String, static_type: NativeType, optional: bool, ) -> Result, AnyError> { let resource = state.resource_table.get::(rid)?; let data_ptr = match resource.get_static(name) { Ok(data_ptr) => Ok(data_ptr), Err(err) => { if optional { let null: v8::Local = v8::null(scope).into(); return Ok(null.into()); } else { Err(err) } } }?; Ok(match static_type { NativeType::Void => { return Err(type_error("Invalid FFI static type 'void'")); } NativeType::Bool => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const bool) }; let boolean: v8::Local = v8::Boolean::new(scope, result).into(); boolean.into() } NativeType::U8 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const u8) }; let number: v8::Local = v8::Integer::new_from_unsigned(scope, result as u32).into(); number.into() } NativeType::I8 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const i8) }; let number: v8::Local = v8::Integer::new(scope, result as i32).into(); number.into() } NativeType::U16 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const u16) }; let number: v8::Local = v8::Integer::new_from_unsigned(scope, result as u32).into(); number.into() } NativeType::I16 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const i16) }; let number: v8::Local = v8::Integer::new(scope, result as i32).into(); number.into() } NativeType::U32 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const u32) }; let number: v8::Local = v8::Integer::new_from_unsigned(scope, result).into(); number.into() } NativeType::I32 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const i32) }; let number: v8::Local = v8::Integer::new(scope, result).into(); number.into() } NativeType::U64 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const u64) }; let integer: v8::Local = if result > MAX_SAFE_INTEGER as u64 { v8::BigInt::new_from_u64(scope, result).into() } else { v8::Number::new(scope, result as f64).into() }; integer.into() } NativeType::I64 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const i64) }; let integer: v8::Local = if result > MAX_SAFE_INTEGER as i64 || result < MIN_SAFE_INTEGER as i64 { v8::BigInt::new_from_i64(scope, result).into() } else { v8::Number::new(scope, result as f64).into() }; integer.into() } NativeType::USize => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const usize) }; let integer: v8::Local = if result > MAX_SAFE_INTEGER as usize { v8::BigInt::new_from_u64(scope, result as u64).into() } else { v8::Number::new(scope, result as f64).into() }; integer.into() } NativeType::ISize => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const isize) }; let integer: v8::Local = if !(MIN_SAFE_INTEGER..=MAX_SAFE_INTEGER).contains(&result) { v8::BigInt::new_from_i64(scope, result as i64).into() } else { v8::Number::new(scope, result as f64).into() }; integer.into() } NativeType::F32 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const f32) }; let number: v8::Local = v8::Number::new(scope, result as f64).into(); number.into() } NativeType::F64 => { // SAFETY: ptr is user provided let result = unsafe { ptr::read_unaligned(data_ptr as *const f64) }; let number: v8::Local = v8::Number::new(scope, result).into(); number.into() } NativeType::Pointer | NativeType::Function | NativeType::Buffer => { let external: v8::Local = v8::External::new(scope, data_ptr as *mut c_void).into(); external.into() } NativeType::Struct(_) => { return Err(type_error("Invalid FFI static type 'struct'")); } }) }