summaryrefslogtreecommitdiff
path: root/ext/ffi/static.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ffi/static.rs')
-rw-r--r--ext/ffi/static.rs146
1 files changed, 146 insertions, 0 deletions
diff --git a/ext/ffi/static.rs b/ext/ffi/static.rs
new file mode 100644
index 000000000..aa0bb325c
--- /dev/null
+++ b/ext/ffi/static.rs
@@ -0,0 +1,146 @@
+// Copyright 2018-2022 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::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,
+) -> Result<serde_v8::Value<'scope>, AnyError> {
+ let resource = state.resource_table.get::<DynamicLibraryResource>(rid)?;
+
+ let data_ptr = resource.get_static(name)?;
+
+ 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::Value> =
+ 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::Value> =
+ 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::Value> =
+ 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::Value> =
+ 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::Value> =
+ 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::Value> =
+ 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::Value> = 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<v8::Value> = 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<v8::Value> = 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<v8::Value> = 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<v8::Value> =
+ 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::Value> =
+ 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::Value> = v8::Number::new(scope, result).into();
+ number.into()
+ }
+ NativeType::Pointer | NativeType::Function | NativeType::Buffer => {
+ let result = data_ptr as u64;
+ let integer: v8::Local<v8::Value> = 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()
+ }
+ })
+}