use crate::array_buffer;
use crate::array_buffer::Allocator as ArrayBufferAllocator;
use crate::support::char;
use crate::support::int;
use crate::support::intptr_t;
use crate::support::Allocated;
use crate::support::Allocation;
use crate::support::Opaque;
use crate::support::SharedPtr;
use std::any::Any;
use std::convert::TryFrom;
use std::iter::once;
use std::mem::size_of;
use std::mem::MaybeUninit;
use std::ptr::null;
#[must_use]
#[derive(Debug, Default)]
pub struct CreateParams {
raw: raw::CreateParams,
allocations: CreateParamAllocations,
}
impl CreateParams {
pub fn snapshot_blob(mut self, data: impl Allocated<[u8]>) -> Self {
let data = Allocation::of(data);
let header = Allocation::of(raw::StartupData::boxed_header(&data));
self.raw.snapshot_blob = &*header;
self.allocations.snapshot_blob_data = Some(data);
self.allocations.snapshot_blob_header = Some(header);
self
}
pub fn array_buffer_allocator(
mut self,
array_buffer_allocator: impl Into<SharedPtr<ArrayBufferAllocator>>,
) -> Self {
self.raw.array_buffer_allocator_shared = array_buffer_allocator.into();
self
}
pub fn external_references(
mut self,
ext_refs: impl Allocated<[intptr_t]>,
) -> Self {
let last_non_null = ext_refs
.iter()
.cloned()
.enumerate()
.rev()
.find_map(|(idx, value)| if value != 0 { Some(idx) } else { None });
let first_null = ext_refs
.iter()
.cloned()
.enumerate()
.find_map(|(idx, value)| if value == 0 { Some(idx) } else { None });
match (last_non_null, first_null) {
(None, _) => {
self.raw.external_references = null();
self.allocations.external_references = None;
}
(_, None) => {
let ext_refs =
ext_refs.iter().cloned().chain(once(0)).collect::<Vec<_>>();
let ext_refs = Allocation::of(ext_refs);
self.raw.external_references = &ext_refs[0];
self.allocations.external_references = Some(ext_refs);
}
(Some(idx1), Some(idx2)) if idx1 + 1 == idx2 => {
let ext_refs = Allocation::of(ext_refs);
self.raw.external_references = &ext_refs[0];
self.allocations.external_references = Some(ext_refs);
}
_ => panic!("unexpected null pointer in external references list"),
}
self
}
pub fn allow_atomics_wait(mut self, value: bool) -> Self {
self.raw.allow_atomics_wait = value;
self
}
pub fn only_terminate_in_safe_scope(mut self, value: bool) -> Self {
self.raw.only_terminate_in_safe_scope = value;
self
}
pub fn embedder_wrapper_type_info_offsets(
mut self,
embedder_wrapper_type_index: int,
embedder_wrapper_object_index: int,
) -> Self {
self.raw.embedder_wrapper_type_index = embedder_wrapper_type_index;
self.raw.embedder_wrapper_object_index = embedder_wrapper_object_index;
self
}
pub fn heap_limits(mut self, initial: usize, max: usize) -> Self {
self
.raw
.constraints
.configure_defaults_from_heap_size(initial, max);
self
}
fn set_fallback_defaults(mut self) -> Self {
if self.raw.array_buffer_allocator_shared.is_null() {
self = self.array_buffer_allocator(array_buffer::new_default_allocator());
}
self
}
pub(crate) fn finalize(mut self) -> (raw::CreateParams, Box<dyn Any>) {
self = self.set_fallback_defaults();
let Self { raw, allocations } = self;
(raw, Box::new(allocations))
}
}
#[derive(Debug, Default)]
struct CreateParamAllocations {
snapshot_blob_data: Option<Allocation<[u8]>>,
snapshot_blob_header: Option<Allocation<raw::StartupData>>,
external_references: Option<Allocation<[intptr_t]>>,
}
pub(crate) mod raw {
use super::*;
use crate::support::long;
use crate::support::Shared;
use crate::support::SharedPtrBase;
use crate::support::UniquePtr;
#[repr(C)]
#[derive(Debug)]
pub(crate) struct CreateParams {
pub code_event_handler: *const Opaque, pub constraints: ResourceConstraints,
pub snapshot_blob: *const StartupData,
pub counter_lookup_callback: *const Opaque, pub create_histogram_callback: *const Opaque, pub add_histogram_sample_callback: *const Opaque, pub array_buffer_allocator: *mut ArrayBufferAllocator,
pub array_buffer_allocator_shared: SharedPtr<ArrayBufferAllocator>,
pub external_references: *const intptr_t,
pub allow_atomics_wait: bool,
pub only_terminate_in_safe_scope: bool,
pub embedder_wrapper_type_index: int,
pub embedder_wrapper_object_index: int,
pub cpp_heap_params: SharedPtr<CppHeapCreateParams>,
pub supported_import_assertions: [usize; 8],
}
extern "C" {
fn v8__Isolate__CreateParams__CONSTRUCT(
buf: *mut MaybeUninit<CreateParams>,
);
fn v8__Isolate__CreateParams__SIZEOF() -> usize;
}
impl Default for CreateParams {
fn default() -> Self {
let size = unsafe { v8__Isolate__CreateParams__SIZEOF() };
assert!(size <= size_of::<Self>());
let mut buf = MaybeUninit::<Self>::uninit();
unsafe { v8__Isolate__CreateParams__CONSTRUCT(&mut buf) };
unsafe { buf.assume_init() }
}
}
#[repr(C)]
#[derive(Debug)]
pub(crate) struct StartupData {
pub data: *const char,
pub raw_size: int,
}
impl StartupData {
pub(super) fn boxed_header(data: &Allocation<[u8]>) -> Box<Self> {
Box::new(Self {
data: &data[0] as *const _ as *const char,
raw_size: int::try_from(data.len()).unwrap(),
})
}
}
#[repr(C)]
#[derive(Debug)]
pub(crate) struct ResourceConstraints {
code_range_size_: usize,
max_old_generation_size_: usize,
max_young_generation_size_: usize,
initial_old_generation_size_: usize,
initial_young_generation_size_: usize,
stack_limit_: *mut u32,
}
extern "C" {
fn v8__ResourceConstraints__ConfigureDefaultsFromHeapSize(
constraints: *mut ResourceConstraints,
initial_heap_size_in_bytes: usize,
maximum_heap_size_in_bytes: usize,
);
}
impl ResourceConstraints {
pub fn configure_defaults_from_heap_size(
&mut self,
initial_heap_size_in_bytes: usize,
maximum_heap_size_in_bytes: usize,
) {
unsafe {
v8__ResourceConstraints__ConfigureDefaultsFromHeapSize(
self,
initial_heap_size_in_bytes,
maximum_heap_size_in_bytes,
)
};
}
}
#[repr(C)]
#[derive(Debug)]
pub(crate) struct CppHeapCreateParams(Opaque);
impl Shared for CppHeapCreateParams {
fn clone(_: &SharedPtrBase<Self>) -> SharedPtrBase<Self> {
todo!()
}
fn from_unique_ptr(_: UniquePtr<Self>) -> SharedPtrBase<Self> {
todo!()
}
fn get(_: &SharedPtrBase<Self>) -> *const Self {
todo!()
}
fn reset(_: &mut SharedPtrBase<Self>) {}
fn use_count(_: &SharedPtrBase<Self>) -> long {
0
}
}
}