use crate::external_references::ExternalReferences;
use crate::isolate_create_params::raw;
use crate::support::char;
use crate::support::int;
use crate::support::Allocated;
use crate::Context;
use crate::Data;
use crate::Isolate;
use crate::Local;
use crate::OwnedIsolate;
use std::borrow::Borrow;
use std::convert::TryFrom;
use std::mem::MaybeUninit;
use std::ops::Deref;
extern "C" {
fn v8__SnapshotCreator__CONSTRUCT(
buf: *mut MaybeUninit<SnapshotCreator>,
params: *const raw::CreateParams,
);
fn v8__SnapshotCreator__DESTRUCT(this: *mut SnapshotCreator);
fn v8__SnapshotCreator__GetIsolate(
this: *const SnapshotCreator,
) -> *mut Isolate;
fn v8__SnapshotCreator__CreateBlob(
this: *mut SnapshotCreator,
function_code_handling: FunctionCodeHandling,
) -> StartupData;
fn v8__SnapshotCreator__SetDefaultContext(
this: *mut SnapshotCreator,
context: *const Context,
);
fn v8__SnapshotCreator__AddContext(
this: *mut SnapshotCreator,
context: *const Context,
) -> usize;
fn v8__SnapshotCreator__AddData_to_isolate(
this: *mut SnapshotCreator,
data: *const Data,
) -> usize;
fn v8__SnapshotCreator__AddData_to_context(
this: *mut SnapshotCreator,
context: *const Context,
data: *const Data,
) -> usize;
fn v8__StartupData__DESTRUCT(this: *mut StartupData);
}
#[repr(C)]
#[derive(Debug)]
pub struct StartupData {
data: *const char,
raw_size: int,
}
impl Drop for StartupData {
fn drop(&mut self) {
unsafe { v8__StartupData__DESTRUCT(self) }
}
}
impl Deref for StartupData {
type Target = [u8];
fn deref(&self) -> &Self::Target {
let data = self.data;
let len = usize::try_from(self.raw_size).unwrap();
unsafe { std::slice::from_raw_parts(data as _, len) }
}
}
impl AsRef<[u8]> for StartupData {
fn as_ref(&self) -> &[u8] {
self
}
}
impl Borrow<[u8]> for StartupData {
fn borrow(&self) -> &[u8] {
self
}
}
#[repr(C)]
#[derive(Debug)]
pub enum FunctionCodeHandling {
Clear,
Keep,
}
#[repr(C)]
#[derive(Debug)]
pub(crate) struct SnapshotCreator([usize; 1]);
impl SnapshotCreator {
#[inline(always)]
#[allow(clippy::new_ret_no_self)]
pub(crate) fn new(
external_references: Option<&'static ExternalReferences>,
) -> OwnedIsolate {
Self::new_impl(external_references, None::<&[u8]>)
}
#[inline(always)]
#[allow(clippy::new_ret_no_self)]
pub(crate) fn from_existing_snapshot(
existing_snapshot_blob: impl Allocated<[u8]>,
external_references: Option<&'static ExternalReferences>,
) -> OwnedIsolate {
Self::new_impl(external_references, Some(existing_snapshot_blob))
}
#[inline(always)]
#[allow(clippy::new_ret_no_self)]
fn new_impl(
external_references: Option<&'static ExternalReferences>,
existing_snapshot_blob: Option<impl Allocated<[u8]>>,
) -> OwnedIsolate {
let mut snapshot_creator: MaybeUninit<Self> = MaybeUninit::uninit();
let mut params = crate::CreateParams::default();
if let Some(external_refs) = external_references {
params = params.external_references(&**external_refs);
}
if let Some(snapshot_blob) = existing_snapshot_blob {
params = params.snapshot_blob(snapshot_blob);
}
let (raw_create_params, create_param_allocations) = params.finalize();
let snapshot_creator = unsafe {
v8__SnapshotCreator__CONSTRUCT(&mut snapshot_creator, &raw_create_params);
snapshot_creator.assume_init()
};
let isolate_ptr =
unsafe { v8__SnapshotCreator__GetIsolate(&snapshot_creator) };
let mut owned_isolate = OwnedIsolate::new_already_entered(isolate_ptr);
owned_isolate.initialize(create_param_allocations);
owned_isolate.set_snapshot_creator(snapshot_creator);
owned_isolate
}
}
impl Drop for SnapshotCreator {
fn drop(&mut self) {
unsafe { v8__SnapshotCreator__DESTRUCT(self) };
}
}
impl SnapshotCreator {
#[inline(always)]
pub(crate) fn set_default_context(&mut self, context: Local<Context>) {
unsafe { v8__SnapshotCreator__SetDefaultContext(self, &*context) };
}
#[inline(always)]
pub(crate) fn add_context(&mut self, context: Local<Context>) -> usize {
unsafe { v8__SnapshotCreator__AddContext(self, &*context) }
}
#[inline(always)]
pub(crate) fn add_isolate_data<T>(&mut self, data: Local<T>) -> usize
where
for<'l> Local<'l, T>: Into<Local<'l, Data>>,
{
unsafe { v8__SnapshotCreator__AddData_to_isolate(self, &*data.into()) }
}
#[inline(always)]
pub(crate) fn add_context_data<T>(
&mut self,
context: Local<Context>,
data: Local<T>,
) -> usize
where
for<'l> Local<'l, T>: Into<Local<'l, Data>>,
{
unsafe {
v8__SnapshotCreator__AddData_to_context(self, &*context, &*data.into())
}
}
#[inline(always)]
pub(crate) fn create_blob(
&mut self,
function_code_handling: FunctionCodeHandling,
) -> Option<StartupData> {
let blob =
unsafe { v8__SnapshotCreator__CreateBlob(self, function_code_handling) };
if blob.data.is_null() {
debug_assert!(blob.raw_size == 0);
None
} else {
debug_assert!(blob.raw_size > 0);
Some(blob)
}
}
}