v8/
fast_api.rs

1use crate::Isolate;
2use crate::Local;
3use crate::Value;
4use crate::binding::*;
5use crate::isolate::RealIsolate;
6use std::ffi::c_void;
7use std::ptr::NonNull;
8
9#[derive(Clone, Copy)]
10#[repr(transparent)]
11pub struct CFunction(v8__CFunction);
12
13impl CFunction {
14  pub const fn new(address: *const c_void, type_info: &CFunctionInfo) -> Self {
15    Self(v8__CFunction {
16      address_: address,
17      type_info_: &type_info.0,
18    })
19  }
20
21  pub const fn address(&self) -> *const c_void {
22    self.0.address_
23  }
24
25  pub const fn type_info(&self) -> &CFunctionInfo {
26    // SAFETY: We initialize this field with a reference. and
27    // the layout of CFunctionInfo is identical to v8_CFunctionInfo.
28    unsafe { &*(self.0.type_info_ as *const CFunctionInfo) }
29  }
30}
31
32#[repr(transparent)]
33pub struct CFunctionInfo(v8__CFunctionInfo);
34
35impl CFunctionInfo {
36  /// Construct a struct to hold a CFunction's type information.
37  /// |return_info| describes the function's return type.
38  /// |arg_info| is an array of |arg_count| CTypeInfos describing the
39  ///   arguments. Only the last argument may be of the special type
40  ///   CTypeInfo::kCallbackOptionsType.
41  pub const fn new(
42    return_info: CTypeInfo,
43    arg_info: &[CTypeInfo],
44    repr: Int64Representation,
45  ) -> Self {
46    Self(v8__CFunctionInfo {
47      arg_count_: arg_info.len() as _,
48      arg_info_: arg_info.as_ptr() as _,
49      repr_: repr as _,
50      return_info_: return_info.0,
51    })
52  }
53}
54
55#[derive(Clone, Copy)]
56#[repr(u8)]
57pub enum Int64Representation {
58  /// Use numbers to represent 64 bit integers.
59  Number = v8_CFunctionInfo_Int64Representation_kNumber,
60  /// Use BigInts to represent 64 bit integers.
61  BigInt = v8_CFunctionInfo_Int64Representation_kBigInt,
62}
63
64#[derive(Clone, Copy)]
65#[repr(transparent)]
66pub struct CTypeInfo(v8_CTypeInfo);
67
68impl CTypeInfo {
69  pub const fn new(r#type: Type, flags: Flags) -> Self {
70    Self(v8_CTypeInfo {
71      type_: r#type as _,
72      flags_: flags.bits(),
73    })
74  }
75}
76
77#[derive(Clone, Copy)]
78#[repr(u8)]
79pub enum Type {
80  Void = v8_CTypeInfo_Type_kVoid,
81  Bool = v8_CTypeInfo_Type_kBool,
82  Uint8 = v8_CTypeInfo_Type_kUint8,
83  Int32 = v8_CTypeInfo_Type_kInt32,
84  Uint32 = v8_CTypeInfo_Type_kUint32,
85  Int64 = v8_CTypeInfo_Type_kInt64,
86  Uint64 = v8_CTypeInfo_Type_kUint64,
87  Float32 = v8_CTypeInfo_Type_kFloat32,
88  Float64 = v8_CTypeInfo_Type_kFloat64,
89  Pointer = v8_CTypeInfo_Type_kPointer,
90  V8Value = v8_CTypeInfo_Type_kV8Value,
91  SeqOneByteString = v8_CTypeInfo_Type_kSeqOneByteString,
92  ApiObject = v8_CTypeInfo_Type_kApiObject,
93  Any = v8_CTypeInfo_Type_kAny,
94  CallbackOptions = 255,
95}
96
97impl Type {
98  // const fn since From<T> is not const
99  pub const fn as_info(self) -> CTypeInfo {
100    CTypeInfo::new(self, Flags::empty())
101  }
102}
103
104impl From<Type> for CTypeInfo {
105  fn from(t: Type) -> Self {
106    Self::new(t, Flags::empty())
107  }
108}
109
110bitflags::bitflags! {
111  pub struct Flags: u8 {
112    /// Must be an ArrayBuffer or TypedArray
113    const AllowShared = v8_CTypeInfo_Flags_kAllowSharedBit;
114    /// T must be integral
115    const EnforceRange = v8_CTypeInfo_Flags_kEnforceRangeBit;
116    /// T must be integral
117    const Clamp = v8_CTypeInfo_Flags_kClampBit;
118    /// T must be float or double
119    const IsRestricted = v8_CTypeInfo_Flags_kIsRestrictedBit;
120  }
121}
122
123/// A struct which may be passed to a fast call callback, like so
124/// ```c
125/// void FastMethodWithOptions(int param, FastApiCallbackOptions& options);
126/// ```
127#[repr(C)]
128pub struct FastApiCallbackOptions<'a> {
129  pub(crate) isolate: *mut RealIsolate,
130  /// The `data` passed to the FunctionTemplate constructor, or `undefined`.
131  pub data: Local<'a, Value>,
132}
133
134impl<'a> FastApiCallbackOptions<'a> {
135  pub unsafe fn isolate_unchecked(&self) -> &'a Isolate {
136    unsafe {
137      Isolate::from_raw_ref(std::mem::transmute::<
138        &*mut RealIsolate,
139        &NonNull<RealIsolate>,
140      >(&self.isolate))
141    }
142  }
143
144  pub unsafe fn isolate_unchecked_mut(&mut self) -> &mut Isolate {
145    unsafe {
146      Isolate::from_raw_ref_mut(std::mem::transmute::<
147        &mut *mut RealIsolate,
148        &mut NonNull<RealIsolate>,
149      >(&mut self.isolate))
150    }
151  }
152}
153
154pub type FastApiOneByteString = v8__FastOneByteString;
155
156impl FastApiOneByteString {
157  #[inline(always)]
158  pub fn as_bytes(&self) -> &[u8] {
159    // Ensure that we never create a null-ptr slice (even a zero-length null-ptr slice
160    // is invalid because of Rust's niche packing).
161    if self.data.is_null() {
162      return &mut [];
163    }
164
165    // SAFETY: The data is guaranteed to be valid for the length of the string.
166    unsafe { std::slice::from_raw_parts(self.data as _, self.length as usize) }
167  }
168}