2022-07-07 16:30:35 +05:30
|
|
|
use crate::support::Opaque;
|
|
|
|
use libc::c_void;
|
2022-07-16 19:57:58 +05:30
|
|
|
use std::{
|
|
|
|
mem::align_of,
|
|
|
|
ptr::{self, NonNull},
|
|
|
|
};
|
2022-07-07 16:30:35 +05:30
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
fn v8__CTypeInfo__New(ty: CType) -> *mut CTypeInfo;
|
|
|
|
fn v8__CTypeInfo__New__From__Slice(
|
|
|
|
len: usize,
|
|
|
|
tys: *const CTypeSequenceInfo,
|
|
|
|
) -> *mut CTypeInfo;
|
|
|
|
fn v8__CFunctionInfo__New(
|
|
|
|
return_info: *const CTypeInfo,
|
|
|
|
args_len: usize,
|
|
|
|
args_info: *const CTypeInfo,
|
|
|
|
) -> *mut CFunctionInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct CFunctionInfo(Opaque);
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct CFunction(Opaque);
|
|
|
|
|
2022-07-16 19:57:58 +05:30
|
|
|
impl CFunctionInfo {
|
2022-07-07 16:30:35 +05:30
|
|
|
pub(crate) unsafe fn new(
|
|
|
|
args: *const CTypeInfo,
|
|
|
|
args_len: usize,
|
|
|
|
return_type: *const CTypeInfo,
|
2022-07-16 19:57:58 +05:30
|
|
|
) -> NonNull<CFunctionInfo> {
|
|
|
|
NonNull::new_unchecked(v8__CFunctionInfo__New(return_type, args_len, args))
|
2022-07-07 16:30:35 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct CTypeInfo(Opaque);
|
|
|
|
|
|
|
|
impl CTypeInfo {
|
|
|
|
pub(crate) fn new(ty: CType) -> NonNull<CTypeInfo> {
|
|
|
|
unsafe { NonNull::new_unchecked(v8__CTypeInfo__New(ty)) }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn new_from_slice(types: &[Type]) -> NonNull<CTypeInfo> {
|
|
|
|
let mut structs = vec![];
|
|
|
|
|
|
|
|
for type_ in types.iter() {
|
|
|
|
structs.push(type_.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
NonNull::new_unchecked(v8__CTypeInfo__New__From__Slice(
|
|
|
|
structs.len(),
|
|
|
|
structs.as_ptr(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
|
|
|
#[repr(u8)]
|
|
|
|
pub enum SequenceType {
|
|
|
|
Scalar,
|
|
|
|
/// sequence<T>
|
|
|
|
IsSequence,
|
|
|
|
/// TypedArray of T or any ArrayBufferView if T is void
|
|
|
|
IsTypedArray,
|
|
|
|
/// ArrayBuffer
|
|
|
|
IsArrayBuffer,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
#[repr(u8)]
|
|
|
|
pub enum CType {
|
|
|
|
Void = 0,
|
|
|
|
Bool,
|
|
|
|
Int32,
|
|
|
|
Uint32,
|
|
|
|
Int64,
|
|
|
|
Uint64,
|
|
|
|
Float32,
|
|
|
|
Float64,
|
|
|
|
V8Value,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
pub enum Type {
|
|
|
|
Void,
|
|
|
|
Bool,
|
|
|
|
Int32,
|
|
|
|
Uint32,
|
|
|
|
Int64,
|
|
|
|
Uint64,
|
|
|
|
Float32,
|
|
|
|
Float64,
|
|
|
|
V8Value,
|
2022-07-08 08:54:24 +05:30
|
|
|
Sequence(CType),
|
|
|
|
TypedArray(CType),
|
|
|
|
ArrayBuffer(CType),
|
2022-07-07 16:30:35 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&Type> for CType {
|
|
|
|
fn from(ty: &Type) -> CType {
|
|
|
|
match ty {
|
|
|
|
Type::Void => CType::Void,
|
|
|
|
Type::Bool => CType::Bool,
|
|
|
|
Type::Int32 => CType::Int32,
|
|
|
|
Type::Uint32 => CType::Uint32,
|
|
|
|
Type::Int64 => CType::Int64,
|
|
|
|
Type::Uint64 => CType::Uint64,
|
|
|
|
Type::Float32 => CType::Float32,
|
|
|
|
Type::Float64 => CType::Float64,
|
|
|
|
Type::V8Value => CType::V8Value,
|
2022-07-08 08:54:24 +05:30
|
|
|
Type::Sequence(ty) => *ty,
|
|
|
|
Type::TypedArray(ty) => *ty,
|
|
|
|
Type::ArrayBuffer(ty) => *ty,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&Type> for SequenceType {
|
|
|
|
fn from(ty: &Type) -> SequenceType {
|
|
|
|
match ty {
|
|
|
|
Type::Sequence(_) => SequenceType::IsSequence,
|
|
|
|
Type::TypedArray(_) => SequenceType::IsTypedArray,
|
|
|
|
Type::ArrayBuffer(_) => SequenceType::IsArrayBuffer,
|
|
|
|
_ => SequenceType::Scalar,
|
2022-07-07 16:30:35 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&Type> for CTypeSequenceInfo {
|
|
|
|
fn from(ty: &Type) -> CTypeSequenceInfo {
|
|
|
|
CTypeSequenceInfo {
|
|
|
|
c_type: ty.into(),
|
2022-07-08 08:54:24 +05:30
|
|
|
sequence_type: ty.into(),
|
2022-07-07 16:30:35 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
struct CTypeSequenceInfo {
|
|
|
|
c_type: CType,
|
|
|
|
sequence_type: SequenceType,
|
|
|
|
}
|
|
|
|
|
2022-07-16 19:57:58 +05:30
|
|
|
// https://source.chromium.org/chromium/chromium/src/+/main:v8/include/v8-fast-api-calls.h;l=336
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct FastApiTypedArray<T: Default> {
|
|
|
|
pub byte_length: usize,
|
|
|
|
// This pointer should include the typed array offset applied.
|
|
|
|
// It's not guaranteed that it's aligned to sizeof(T), it's only
|
|
|
|
// guaranteed that it's 4-byte aligned, so for 8-byte types we need to
|
|
|
|
// provide a special implementation for reading from it, which hides
|
|
|
|
// the possibly unaligned read in the `get` method.
|
|
|
|
data: *mut T,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Default> FastApiTypedArray<T> {
|
|
|
|
#[inline]
|
|
|
|
pub fn get(&self, index: usize) -> T {
|
|
|
|
debug_assert!(index < self.byte_length);
|
|
|
|
let mut t: T = Default::default();
|
|
|
|
unsafe {
|
|
|
|
ptr::copy_nonoverlapping(self.data.add(index), &mut t, 1);
|
|
|
|
}
|
|
|
|
t
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn get_storage_if_aligned(&self) -> Option<&mut [T]> {
|
|
|
|
if (self.data as usize) % align_of::<T>() != 0 {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
Some(unsafe {
|
|
|
|
std::slice::from_raw_parts_mut(
|
|
|
|
self.data,
|
|
|
|
self.byte_length / align_of::<T>(),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-07 16:30:35 +05:30
|
|
|
pub trait FastFunction {
|
|
|
|
fn args(&self) -> &'static [Type] {
|
|
|
|
&[]
|
|
|
|
}
|
|
|
|
fn return_type(&self) -> CType {
|
|
|
|
CType::Void
|
|
|
|
}
|
2022-07-16 19:57:58 +05:30
|
|
|
fn function(&self) -> *const c_void;
|
2022-07-07 16:30:35 +05:30
|
|
|
}
|