0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2025-03-11 22:47:12 -04:00
rusty-v8/src/fast_api.rs

197 lines
4.1 KiB
Rust
Raw Normal View History

use crate::support::Opaque;
use libc::c_void;
2022-07-16 19:57:58 +05:30
use std::{
mem::align_of,
ptr::{self, NonNull},
};
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 {
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))
}
}
#[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,
Sequence(CType),
TypedArray(CType),
ArrayBuffer(CType),
}
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,
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,
}
}
}
impl From<&Type> for CTypeSequenceInfo {
fn from(ty: &Type) -> CTypeSequenceInfo {
CTypeSequenceInfo {
c_type: ty.into(),
sequence_type: ty.into(),
}
}
}
#[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>(),
)
})
}
}
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;
}