Skip to content

Commit 194ac66

Browse files
authored
feat: Allow User to extend enums (#8)
Enum mappers are now a bit different, you declare your enums as usual in C++, but then add the converter functions to the `EnumMapper` namespace: ```cpp namespace margelo { // 1. Create your C++ enum enum Backend { METAL, OPEN_GL, VULKAN }; namespace EnumMapper { // 2. Add JS Union -> C++ Enum converter for your enum specifically static void convertJSUnionToEnum(const std::string& inUnion, Backend* outEnum) { if (inUnion == "metal") *outEnum = METAL; else if (inUnion == "open-gl") *outEnum = OPEN_GL; else if (inUnion == "vulkan") *outEnum = VULKAN; else throw invalidUnion(inUnion); } // 3. Add C++ Enum -> JS Union converter for your enum specifically static void convertEnumToJSUnion(Backend inEnum, std::string* outUnion) { switch (inEnum) { case METAL: *outUnion = "metal"; break; case OPEN_GL: *outUnion = "open-gl"; break; case VULKAN: *outUnion = "vulkan"; break; default: throw invalidEnum(inEnum); } } } // namespace EnumMapper } // namespace margelo ```
1 parent ba2313a commit 194ac66

File tree

3 files changed

+50
-47
lines changed

3 files changed

+50
-47
lines changed

package/cpp/jsi/EnumMapper.h

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,57 +4,30 @@
44

55
#pragma once
66

7-
#include "test/TestEnum.h"
8-
#include <unordered_map>
7+
#include <stdexcept>
8+
#include <string>
99

1010
namespace margelo {
1111

12-
using namespace facebook;
12+
namespace EnumMapper {
13+
// Add these two methods in namespace "EnumMapper" to allow parsing a custom enum:
14+
// 1. `static void convertJSUnionToEnum(const std::string& inUnion, Enum* outEnum)`
15+
// 2. `static void convertEnumToJSUnion(Enum inEnum, std::string* outUnion)`
1316

14-
static std::runtime_error invalidUnion(const std::string jsUnion) {
15-
return std::runtime_error("Cannot convert JS Value to Enum: Invalid Union value passed! (\"" + jsUnion + "\")");
16-
}
17-
template <typename Enum> static std::runtime_error invalidEnum(Enum passedEnum) {
18-
return std::runtime_error("Cannot convert Enum to JS Value: Invalid Enum passed! (Value #" + std::to_string(passedEnum) +
19-
" does not exist in " + typeid(Enum).name() + ")");
20-
}
21-
22-
template <typename Enum> struct EnumMapper {
23-
static Enum fromJSUnion(const std::string&) {
24-
static_assert(always_false<Enum>::value, "This type is not supported by the EnumMapper!");
25-
return Enum();
17+
static std::runtime_error invalidUnion(const std::string& passedUnion) {
18+
return std::runtime_error("Cannot convert JS Value to Enum: Invalid Union value passed! (\"" + std::string(passedUnion) + "\")");
2619
}
27-
static std::string toJSUnion(Enum) {
28-
static_assert(always_false<Enum>::value, "This type is not supported by the EnumMapper!");
29-
return std::string();
20+
static std::runtime_error invalidEnum(int passedEnum) {
21+
return std::runtime_error("Cannot convert Enum to JS Value: Invalid Enum passed! (Value #" + std::to_string(passedEnum) + ")");
3022
}
3123

32-
private:
33-
template <typename> struct always_false : std::false_type {};
34-
};
35-
36-
template <> struct EnumMapper<TestEnum> {
37-
public:
38-
static constexpr TestEnum fromJSUnion(const std::string& jsUnion) {
39-
if (jsUnion == "first")
40-
return FIRST;
41-
if (jsUnion == "second")
42-
return SECOND;
43-
if (jsUnion == "third")
44-
return THIRD;
45-
throw invalidUnion(jsUnion);
24+
static void convertJSUnionToEnum(const std::string& inUnion, int*) {
25+
throw invalidUnion(inUnion);
4626
}
47-
static std::string toJSUnion(TestEnum value) {
48-
switch (value) {
49-
case FIRST:
50-
return "first";
51-
case SECOND:
52-
return "second";
53-
case THIRD:
54-
return "third";
55-
}
56-
throw invalidEnum(value);
27+
28+
static void convertEnumToJSUnion(int inEnum, std::string*) {
29+
throw invalidEnum(inEnum);
5730
}
58-
};
31+
} // namespace EnumMapper
5932

6033
} // namespace margelo

package/cpp/jsi/JSIConverter.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,14 @@ template <typename TInner> struct JSIConverter<std::optional<TInner>> {
104104
template <typename TEnum> struct JSIConverter<TEnum, std::enable_if_t<std::is_enum<TEnum>::value>> {
105105
static TEnum fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
106106
std::string string = arg.asString(runtime).utf8(runtime);
107-
return EnumMapper<TEnum>::fromJSUnion(string);
107+
TEnum outEnum;
108+
EnumMapper::convertJSUnionToEnum(string, &outEnum);
109+
return outEnum;
108110
}
109111
static jsi::Value toJSI(jsi::Runtime& runtime, TEnum arg) {
110-
std::string string = EnumMapper<TEnum>::toJSUnion(arg);
111-
return jsi::String::createFromUtf8(runtime, string);
112+
std::string outUnion;
113+
EnumMapper::convertEnumToJSUnion(arg, &outUnion);
114+
return jsi::String::createFromUtf8(runtime, outUnion);
112115
}
113116
};
114117

package/cpp/test/TestEnum.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,31 @@ namespace margelo {
1010

1111
enum TestEnum { FIRST, SECOND, THIRD };
1212

13-
}
13+
namespace EnumMapper {
14+
static void convertJSUnionToEnum(const std::string& inUnion, TestEnum* outEnum) {
15+
if (inUnion == "first")
16+
*outEnum = FIRST;
17+
else if (inUnion == "second")
18+
*outEnum = SECOND;
19+
else if (inUnion == "third")
20+
*outEnum = THIRD;
21+
else
22+
throw invalidUnion(inUnion);
23+
}
24+
static void convertEnumToJSUnion(TestEnum inEnum, std::string* outUnion) {
25+
switch (inEnum) {
26+
case FIRST:
27+
*outUnion = "first";
28+
break;
29+
case SECOND:
30+
*outUnion = "second";
31+
break;
32+
case THIRD:
33+
*outUnion = "third";
34+
break;
35+
default:
36+
throw invalidEnum(inEnum);
37+
}
38+
}
39+
} // namespace EnumMapper
40+
} // namespace margelo

0 commit comments

Comments
 (0)