deno/ext/ffi/static.rs
林炳权 2080669943
chore: update to Rust 1.72 (#20258)
<!--
Before submitting a PR, please read https://deno.com/manual/contributing

1. Give the PR a descriptive title.

  Examples of good title:
    - fix(std/http): Fix race condition in server
    - docs(console): Update docstrings
    - feat(doc): Handle nested reexports

  Examples of bad title:
    - fix #7123
    - update docs
    - fix bugs

2. Ensure there is a related issue and it is referenced in the PR text.
3. Ensure there are tests that cover the changes.
4. Ensure `cargo test` passes.
5. Ensure `./tools/format.js` passes without changing files.
6. Ensure `./tools/lint.js` passes.
7. Open as a draft PR if your work is still in progress. The CI won't
run
   all steps, but you can add '[ci]' to a commit message to force it to.
8. If you would like to run the benchmarks on the CI, add the 'ci-bench'
label.
-->

As the title.

---------

Co-authored-by: Matt Mastracci <matthew@mastracci.com>
2023-08-26 22:04:12 -06:00

156 lines
5.2 KiB
Rust

// 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::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<serde_v8::Value<'scope>, AnyError> {
let resource = state.resource_table.get::<DynamicLibraryResource>(rid)?;
let data_ptr = match resource.get_static(name) {
Ok(data_ptr) => Ok(data_ptr),
Err(err) => {
if optional {
let null: v8::Local<v8::Value> = 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::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 external: v8::Local<v8::Value> =
v8::External::new(scope, data_ptr).into();
external.into()
}
NativeType::Struct(_) => {
return Err(type_error("Invalid FFI static type 'struct'"));
}
})
}