+void Function::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+ _assert(false);
+}
+
+// XXX: this code is getting worse, not better :/
+
+#define CYFromFFI_(Type_) \
+template <> \
+JSValueRef Primitive<Type_>::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { \
+ JSValueRef value(CYCastJSValue(context, *reinterpret_cast<Type_ *>(data))); \
+ JSObjectRef typed(_jsccall(JSObjectCallAsConstructor, context, CYGetCachedObject(context, CYJSString("Number")), 1, &value)); \
+ CYSetProperty(context, typed, cyt__s, CYMakeType(context, *this), kJSPropertyAttributeDontEnum); \
+ return typed; \
+}
+
+#define CYFromFFI_2(Type_) \
+template <> \
+JSValueRef Primitive<Type_>::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { \
+ return CYCastJSValue(context, *reinterpret_cast<Type_ *>(data)); \
+}
+
+CYFromFFI_(wchar_t)
+CYFromFFI_(float)
+CYFromFFI_(double)
+CYFromFFI_(long double)
+
+CYFromFFI_2(signed char)
+CYFromFFI_2(signed int)
+CYFromFFI_(signed long int)
+CYFromFFI_(signed long long int)
+CYFromFFI_2(signed short int)
+
+CYFromFFI_2(unsigned char)
+CYFromFFI_2(unsigned int)
+CYFromFFI_(unsigned long int)
+CYFromFFI_(unsigned long long int)
+CYFromFFI_2(unsigned short int)
+
+#ifdef __SIZEOF_INT128__
+CYFromFFI_(signed __int128)
+CYFromFFI_(unsigned __int128)
+#endif
+
+template <>
+JSValueRef Primitive<bool>::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ return CYCastJSValue(context, *reinterpret_cast<bool *>(data));
+}
+
+template <>
+JSValueRef Primitive<char>::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ uint16_t string(uint8_t(*reinterpret_cast<char *>(data)));
+ JSValueRef value(CYCastJSValue(context, CYJSString(CYUTF16String(&string, 1))));
+ JSObjectRef typed(_jsccall(JSObjectCallAsConstructor, context, CYGetCachedObject(context, CYJSString("String")), 1, &value));
+ CYSetProperty(context, typed, cyt_s, CYMakeType(context, sig::Primitive<char>()), kJSPropertyAttributeDontEnum);
+ CYSetPrototype(context, typed, CYGetCachedValue(context, CYJSString("Character_prototype")));
+ return typed;
+}
+
+JSValueRef Void::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ return CYJSUndefined(context);
+}
+
+JSValueRef Unknown::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ _assert(false);
+}
+
+JSValueRef String::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ if (char *value = *reinterpret_cast<char **>(data))
+ return CYPrivate<CString>::Make(context, value, context, owner);
+ return CYJSNull(context);
+}
+
+JSValueRef Bits::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ _assert(false);
+}
+
+JSValueRef Pointer::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ if (void *value = *reinterpret_cast<void **>(data))
+ return CYMakePointer(context, value, type, NULL, owner);
+ return CYJSNull(context);
+}
+
+JSValueRef Array::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ return CYPrivate<CArray>::Make(context, data, size, type, ffi->elements[0], context, owner);
+}
+
+JSValueRef Enum::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ return type.FromFFI(context, ffi, data, initialize, owner);
+}
+
+JSValueRef Aggregate::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ _assert(!overlap);
+ _assert(signature.count != _not(size_t));
+ return CYPrivate<Struct_privateData>::Make(context, data, *this, ffi, context, owner);
+}
+
+JSValueRef Function::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+ return CYMakeFunctor(context, reinterpret_cast<void (*)()>(data), variadic, signature);
+}
+
+}
+