diff --git a/package/cpp/jsi/EnumMapper.h b/package/cpp/jsi/EnumMapper.h new file mode 100644 index 00000000..45ca9185 --- /dev/null +++ b/package/cpp/jsi/EnumMapper.h @@ -0,0 +1,60 @@ +// +// Created by Marc Rousavy on 22.02.24. +// + +#pragma once + +#include "test/TestEnum.h" +#include + +namespace margelo { + +using namespace facebook; + +static std::runtime_error invalidUnion(const std::string jsUnion) { + return std::runtime_error("Cannot convert JS Value to Enum: Invalid Union value passed! (\"" + jsUnion + "\")"); +} +template static std::runtime_error invalidEnum(Enum passedEnum) { + return std::runtime_error("Cannot convert Enum to JS Value: Invalid Enum passed! (Value #" + std::to_string(passedEnum) + + " does not exist in " + typeid(Enum).name() + ")"); +} + +template struct EnumMapper { + static Enum fromJSUnion(const std::string&) { + static_assert(always_false::value, "This type is not supported by the EnumMapper!"); + return Enum(); + } + static std::string toJSUnion(Enum) { + static_assert(always_false::value, "This type is not supported by the EnumMapper!"); + return std::string(); + } + +private: + template struct always_false : std::false_type {}; +}; + +template <> struct EnumMapper { +public: + static constexpr TestEnum fromJSUnion(const std::string& jsUnion) { + if (jsUnion == "first") + return FIRST; + if (jsUnion == "second") + return SECOND; + if (jsUnion == "third") + return THIRD; + throw invalidUnion(jsUnion); + } + static std::string toJSUnion(TestEnum value) { + switch (value) { + case FIRST: + return "first"; + case SECOND: + return "second"; + case THIRD: + return "third"; + } + throw invalidEnum(value); + } +}; + +} // namespace margelo diff --git a/package/cpp/jsi/JSIConverter.h b/package/cpp/jsi/JSIConverter.h index ede4f4c0..2320c7ae 100644 --- a/package/cpp/jsi/JSIConverter.h +++ b/package/cpp/jsi/JSIConverter.h @@ -4,6 +4,7 @@ #pragma once +#include "EnumMapper.h" #include "HybridObject.h" #include #include @@ -100,6 +101,17 @@ template struct JSIConverter> { } }; +template struct JSIConverter::value>> { + static TEnum fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string string = arg.asString(runtime).utf8(runtime); + return EnumMapper::fromJSUnion(string); + } + static jsi::Value toJSI(jsi::Runtime& runtime, TEnum arg) { + std::string string = EnumMapper::toJSUnion(arg); + return jsi::String::createFromUtf8(runtime, string); + } +}; + template struct JSIConverter> { static std::function fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Function function = arg.asObject(runtime).asFunction(runtime); diff --git a/package/cpp/test/TestEnum.h b/package/cpp/test/TestEnum.h new file mode 100644 index 00000000..87775541 --- /dev/null +++ b/package/cpp/test/TestEnum.h @@ -0,0 +1,13 @@ +// +// Created by Marc Rousavy on 22.02.24. +// + +#pragma once + +#include "jsi/EnumMapper.h" + +namespace margelo { + +enum TestEnum { FIRST, SECOND, THIRD }; + +} \ No newline at end of file diff --git a/package/cpp/test/TestHybridObject.cpp b/package/cpp/test/TestHybridObject.cpp index 6cd5c9db..1c8ab4d3 100644 --- a/package/cpp/test/TestHybridObject.cpp +++ b/package/cpp/test/TestHybridObject.cpp @@ -12,6 +12,9 @@ void TestHybridObject::loadHybridMethods() { // this.string get & set registerHybridGetter("string", &TestHybridObject::getString, this); registerHybridSetter("string", &TestHybridObject::setString, this); + // this.enum + registerHybridGetter("enum", &TestHybridObject::getEnum, this); + registerHybridSetter("enum", &TestHybridObject::setEnum, this); // methods registerHybridMethod("multipleArguments", &TestHybridObject::multipleArguments, this); // callbacks diff --git a/package/cpp/test/TestHybridObject.h b/package/cpp/test/TestHybridObject.h index 48e26224..d9c89ec0 100644 --- a/package/cpp/test/TestHybridObject.h +++ b/package/cpp/test/TestHybridObject.h @@ -4,6 +4,7 @@ #pragma once +#include "TestEnum.h" #include "jsi/HybridObject.h" #include #include @@ -24,6 +25,12 @@ class TestHybridObject : public HybridObject { void setString(std::string newValue) { _string = newValue; } + void setEnum(TestEnum testEnum) { + _enum = testEnum; + } + TestEnum getEnum() { + return _enum; + } std::unordered_map multipleArguments(int first, bool second, std::string third) { return std::unordered_map{{"first", 5312}, {"second", 532233}, {"third", 2786}}; @@ -42,6 +49,7 @@ class TestHybridObject : public HybridObject { private: int _int; std::string _string; + TestEnum _enum; void loadHybridMethods() override; }; diff --git a/package/src/native/FilamentProxy.ts b/package/src/native/FilamentProxy.ts index 44394021..b78c30d9 100644 --- a/package/src/native/FilamentProxy.ts +++ b/package/src/native/FilamentProxy.ts @@ -8,6 +8,7 @@ interface TestHybridObject { getIntGetter(): () => number sayHelloCallback(callback: () => string): void createNewHybridObject: () => TestHybridObject + enum: 'first' | 'second' | 'third' } export interface TFilamentProxy { diff --git a/package/src/test/TestHybridObject.ts b/package/src/test/TestHybridObject.ts index b402f2aa..02195d1e 100644 --- a/package/src/test/TestHybridObject.ts +++ b/package/src/test/TestHybridObject.ts @@ -15,21 +15,26 @@ export function testHybridObject() { hybridObject.int = 6723 console.log(`New Int: ${hybridObject.int}`) - // 4. String Getter & Setter + // 4. Enum Getter & Setter + console.log(`Enum: ${hybridObject.enum}`) + hybridObject.enum = 'second' + console.log(`New Enum: ${hybridObject.enum}`) + + // 5. String Getter & Setter console.log(`String: ${hybridObject.string}`) hybridObject.string = 'new string value!' console.log(`New String: ${hybridObject.string}`) - // 5. Testing multiple arguments and maps + // 6. Testing multiple arguments and maps const result = hybridObject.multipleArguments(5, true, 'hahah!') console.log(`multipleArguments() -> ${JSON.stringify(result)}`) - // 6. Testing callbacks + // 7. Testing callbacks hybridObject.sayHelloCallback(() => 'hello from JS!') const getter = hybridObject.getIntGetter() console.log(`Int getter: ${getter()}`) - // 7. Create a new one + // 8. Create a new one const newObject = hybridObject.createNewHybridObject() console.log(`Created new hybrid object!`, newObject)