#ifndef SUPPORT_H_
#define SUPPORT_H_
#include <algorithm>
#include <array>
#include <cassert>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
#include "v8/include/v8.h"
template <>
template <>
inline void v8::internal::CastCheck<true>::Perform<v8::Data>(v8::Data* data) {}
static_assert(sizeof(bool) == sizeof(uint8_t), "");
static_assert(sizeof(std::unique_ptr<void>) == sizeof(void*), "");
namespace support {
template <class T>
using uninit_t = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
template <class T, class... Args>
class construct_in_place_helper {
public:
construct_in_place_helper(uninit_t<T>* buf, Args... args)
: inner_(std::forward<Args>(args)...) {}
private:
T inner_;
};
template <class T, class... Args>
void construct_in_place(uninit_t<T>* buf, Args... args) {
new (buf)
construct_in_place_helper<T, Args...>(buf, std::forward<Args>(args)...);
}
template <class P>
struct make_pod {
template <class V>
inline make_pod(V&& value) : pod_(helper<V>(std::move(value))) {}
template <class V>
inline make_pod(const V& value) : pod_(helper<V>(value)) {}
inline operator P() { return pod_; }
private:
P pod_;
template <class V>
union helper {
static_assert(std::is_pod<P>::value, "type P must a pod type");
static_assert(sizeof(V) == sizeof(P), "type P must be same size as type V");
static_assert(alignof(V) == alignof(P),
"alignment of type P must be compatible with that of type V");
inline helper(V&& value) : value_(std::move(value)) {}
inline helper(const V& value) : value_(value) {}
inline ~helper() {}
inline operator P() {
P result;
memcpy(&result, this, sizeof result);
return result;
}
private:
V value_;
};
};
enum class MaybeBool { JustFalse = 0, JustTrue = 1, Nothing = 2 };
inline static MaybeBool maybe_to_maybe_bool(v8::Maybe<bool> maybe) {
if (maybe.IsNothing()) {
return MaybeBool::Nothing;
} else if (maybe.FromJust()) {
return MaybeBool::JustTrue;
} else {
return MaybeBool::JustFalse;
}
}
inline static v8::Maybe<bool> maybe_bool_to_maybe(MaybeBool maybe) {
switch (maybe) {
case MaybeBool::JustTrue:
case MaybeBool::JustFalse:
return v8::Just<bool>(maybe == MaybeBool::JustTrue);
default:
return v8::Nothing<bool>();
}
}
template <class T>
inline static T* local_to_ptr(v8::Local<T> local) {
return *local;
}
template <class T>
inline static const v8::Local<T> ptr_to_local(const T* ptr) {
static_assert(sizeof(v8::Local<T>) == sizeof(T*), "");
auto local = *reinterpret_cast<const v8::Local<T>*>(&ptr);
assert(*local == ptr);
return local;
}
template <class T>
inline static v8::Local<T>* const_ptr_array_to_local_array(
const T* const ptr_array[]) {
static_assert(sizeof(v8::Local<T>[42]) == sizeof(T* [42]), "");
auto mut_ptr_array = const_cast<T**>(ptr_array);
auto mut_local_array = reinterpret_cast<v8::Local<T>*>(mut_ptr_array);
return mut_local_array;
}
template <class T>
inline static T* maybe_local_to_ptr(v8::MaybeLocal<T> local) {
return *local.FromMaybe(v8::Local<T>());
}
template <class T>
inline static const v8::MaybeLocal<T> ptr_to_maybe_local(const T* ptr) {
static_assert(sizeof(v8::MaybeLocal<T>) == sizeof(T*), "");
return *reinterpret_cast<const v8::MaybeLocal<T>*>(&ptr);
}
template <class T>
inline static v8::Global<T> ptr_to_global(const T* ptr) {
v8::Global<T> global;
std::swap(ptr, *reinterpret_cast<const T**>(&global));
return global;
}
struct two_pointers_t {
void* a;
void* b;
};
struct three_pointers_t {
void* a;
void* b;
void* c;
};
}
#endif