// // Created by Marc Rousavy on 22.06.21. // #include "JSIJNIConversion.h" #include #include #include #include #include #include #include #include "FrameHostObject.h" #include "JFrame.h" namespace vision { using namespace facebook; jni::local_ref JSIJNIConversion::convertJSIValueToJNIObject(jsi::Runtime& runtime, const jsi::Value& value) { if (value.isNull() || value.isUndefined()) { // null return nullptr; } else if (value.isBool()) { // Boolean bool boolean = value.getBool(); return JBoolean::valueOf(boolean); } else if (value.isNumber()) { // Double double number = value.getNumber(); return jni::JDouble::valueOf(number); } else if (value.isString()) { // String std::string string = value.getString(runtime).utf8(runtime); return jni::make_jstring(string); } else if (value.isObject()) { // Object auto valueAsObject = value.getObject(runtime); if (valueAsObject.isArray(runtime)) { // List jsi::Array array = valueAsObject.getArray(runtime); size_t size = array.size(runtime); jni::local_ref> arrayList = jni::JArrayList::create(static_cast(size)); for (size_t i = 0; i < size; i++) { jsi::Value item = array.getValueAtIndex(runtime, i); jni::local_ref jniItem = convertJSIValueToJNIObject(runtime, item); arrayList->add(jniItem); } return arrayList; } else if (valueAsObject.isHostObject(runtime)) { throw std::runtime_error("You can't pass HostObjects here."); } else { // Map jsi::Array propertyNames = valueAsObject.getPropertyNames(runtime); size_t size = propertyNames.size(runtime); jni::local_ref> hashMap = jni::JHashMap::create(); for (size_t i = 0; i < size; i++) { jsi::String propName = propertyNames.getValueAtIndex(runtime, i).asString(runtime); jsi::Value item = valueAsObject.getProperty(runtime, propName); jni::local_ref key = jni::make_jstring(propName.utf8(runtime)); jni::local_ref jniItem = convertJSIValueToJNIObject(runtime, item); hashMap->put(key, jniItem); } return hashMap; } } else { auto stringRepresentation = value.toString(runtime).utf8(runtime); throw std::runtime_error("Failed to convert jsi::Value to JNI value - unsupported type!" + stringRepresentation); } } jni::local_ref> JSIJNIConversion::convertJSIObjectToJNIMap(jsi::Runtime& runtime, const jsi::Object& object) { auto propertyNames = object.getPropertyNames(runtime); auto size = propertyNames.size(runtime); auto hashMap = jni::JHashMap::create(); for (size_t i = 0; i < size; i++) { jsi::String propName = propertyNames.getValueAtIndex(runtime, i).asString(runtime); jsi::Value value = object.getProperty(runtime, propName); jni::local_ref key = jni::make_jstring(propName.utf8(runtime)); jni::local_ref jniValue = convertJSIValueToJNIObject(runtime, value); hashMap->put(key, jniValue); } return hashMap; } jsi::Value JSIJNIConversion::convertJNIObjectToJSIValue(jsi::Runtime& runtime, const jni::local_ref& object) { if (object == nullptr) { // null return jsi::Value::undefined(); } else if (object->isInstanceOf(jni::JBoolean::javaClassStatic())) { // Boolean auto boxed = static_ref_cast(object); bool value = boxed->value(); return jsi::Value(value); } else if (object->isInstanceOf(jni::JDouble::javaClassStatic())) { // Double auto boxed = static_ref_cast(object); double value = boxed->value(); return jsi::Value(value); } else if (object->isInstanceOf(jni::JInteger::javaClassStatic())) { // Integer auto boxed = static_ref_cast(object); return jsi::Value(boxed->value()); } else if (object->isInstanceOf(jni::JString::javaClassStatic())) { // String return jsi::String::createFromUtf8(runtime, object->toString()); } else if (object->isInstanceOf(JList::javaClassStatic())) { // List auto arrayList = static_ref_cast>(object); auto size = arrayList->size(); auto result = jsi::Array(runtime, size); size_t i = 0; for (const auto& item : *arrayList) { result.setValueAtIndex(runtime, i, convertJNIObjectToJSIValue(runtime, item)); i++; } return result; } else if (object->isInstanceOf(JMap::javaClassStatic())) { // Map auto map = static_ref_cast>(object); auto result = jsi::Object(runtime); for (const auto& entry : *map) { auto key = entry.first->toString(); auto value = entry.second; auto jsiValue = convertJNIObjectToJSIValue(runtime, value); result.setProperty(runtime, key.c_str(), jsiValue); } return result; } else if (object->isInstanceOf(JFrame::javaClassStatic())) { // Frame auto frame = static_ref_cast(object); // box into HostObject auto hostObject = std::make_shared(frame); return jsi::Object::createFromHostObject(runtime, hostObject); } auto type = object->getClass()->toString(); auto message = "Received unknown JNI type \"" + type + "\"! Cannot convert to jsi::Value."; __android_log_write(ANDROID_LOG_ERROR, "VisionCamera", message.c_str()); throw std::runtime_error(message); } } // namespace vision