react-native-nitro-modules 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/NitroModules.podspec +3 -1
  2. package/README.md +33 -14
  3. package/android/gradle.properties +5 -5
  4. package/android/src/main/cpp/JNIOnLoad.cpp +8 -0
  5. package/android/src/main/cpp/core/ByteBufferArrayBuffer.hpp +47 -0
  6. package/android/src/main/cpp/core/JAnyMap.hpp +193 -0
  7. package/android/src/main/cpp/core/JAnyValue.hpp +191 -0
  8. package/android/src/main/cpp/core/JArrayBuffer.hpp +124 -0
  9. package/android/src/main/cpp/core/JHybridObject.hpp +11 -4
  10. package/android/src/main/cpp/core/JPromise.hpp +88 -0
  11. package/android/src/main/cpp/platform/NitroLogger.cpp +36 -0
  12. package/android/src/main/cpp/registry/JHybridObjectInitializer.hpp +1 -1
  13. package/android/src/main/cpp/registry/JHybridObjectRegistry.cpp +1 -1
  14. package/android/src/main/cpp/registry/JHybridObjectRegistry.hpp +1 -1
  15. package/android/src/main/cpp/utils/{JNISharedPtr.h → JNISharedPtr.hpp} +13 -1
  16. package/android/src/main/java/com/margelo/nitro/JNIOnLoad.java +27 -0
  17. package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.java +1 -9
  18. package/android/src/main/java/com/margelo/nitro/core/AnyMap.kt +80 -0
  19. package/android/src/main/java/com/margelo/nitro/core/AnyValue.kt +164 -0
  20. package/android/src/main/java/com/margelo/nitro/core/ArrayBuffer.kt +115 -0
  21. package/android/src/main/java/com/margelo/nitro/{HybridObject.kt → core/HybridObject.kt} +12 -15
  22. package/android/src/main/java/com/margelo/nitro/{HybridObjectInitializer.java → core/HybridObjectInitializer.java} +1 -1
  23. package/android/src/main/java/com/margelo/nitro/{HybridObjectRegistry.java → core/HybridObjectRegistry.java} +6 -4
  24. package/android/src/main/java/com/margelo/nitro/core/Promise.kt +115 -0
  25. package/cpp/core/AnyMap.hpp +2 -2
  26. package/cpp/core/ArrayBuffer.cpp +5 -5
  27. package/cpp/core/ArrayBuffer.hpp +7 -9
  28. package/cpp/core/HybridFunction.hpp +120 -46
  29. package/cpp/core/HybridObject.cpp +17 -6
  30. package/cpp/core/HybridObject.hpp +32 -8
  31. package/cpp/jsi/JSICache.cpp +5 -5
  32. package/cpp/jsi/JSICache.hpp +1 -3
  33. package/cpp/jsi/JSIConverter+AnyMap.hpp +2 -2
  34. package/cpp/jsi/JSIConverter+ArrayBuffer.hpp +2 -2
  35. package/cpp/jsi/JSIConverter+Function.hpp +7 -6
  36. package/cpp/jsi/JSIConverter+HybridObject.hpp +6 -5
  37. package/cpp/jsi/JSIConverter+Optional.hpp +1 -1
  38. package/cpp/jsi/JSIConverter+Promise.hpp +5 -4
  39. package/cpp/jsi/JSIConverter+Tuple.hpp +1 -1
  40. package/cpp/jsi/JSIConverter+UnorderedMap.hpp +1 -1
  41. package/cpp/jsi/JSIConverter+Variant.hpp +1 -3
  42. package/cpp/jsi/JSIConverter+Vector.hpp +1 -1
  43. package/cpp/jsi/JSIConverter.hpp +11 -11
  44. package/cpp/jsi/JSPromise.cpp +2 -2
  45. package/cpp/platform/NitroLogger.hpp +67 -0
  46. package/cpp/prototype/HybridObjectPrototype.cpp +2 -2
  47. package/cpp/prototype/Prototype.hpp +43 -22
  48. package/cpp/registry/HybridObjectRegistry.cpp +4 -4
  49. package/cpp/threading/Dispatcher.cpp +4 -3
  50. package/cpp/threading/ThreadPool.cpp +2 -2
  51. package/cpp/turbomodule/NativeNitroModules.cpp +26 -8
  52. package/cpp/turbomodule/NativeNitroModules.h +1 -0
  53. package/cpp/turbomodule/NativeNitroModules.hpp +2 -0
  54. package/cpp/utils/TypeInfo.hpp +14 -0
  55. package/ios/core/AnyMapHolder.hpp +91 -0
  56. package/ios/core/AnyMapHolder.swift +316 -0
  57. package/ios/core/ArrayBufferHolder.hpp +7 -5
  58. package/ios/core/ArrayBufferHolder.swift +22 -7
  59. package/ios/core/HybridContext.hpp +3 -3
  60. package/ios/core/Promise.swift +20 -0
  61. package/ios/core/PromiseHolder.hpp +15 -11
  62. package/ios/platform/NitroLogger.mm +36 -0
  63. package/ios/platform/ThreadUtils.cpp +1 -1
  64. package/ios/turbomodule/NitroModuleOnLoad.mm +2 -1
  65. package/ios/utils/SwiftClosure.hpp +63 -0
  66. package/ios/utils/SwiftClosure.swift +58 -0
  67. package/lib/AnyMap.d.ts +3 -0
  68. package/lib/HybridObject.d.ts +15 -0
  69. package/lib/NativeNitroModules.d.ts +2 -0
  70. package/lib/NitroModules.d.ts +18 -0
  71. package/lib/NitroModules.js +24 -0
  72. package/lib/commonjs/NativeNitroModules.js.map +1 -1
  73. package/lib/commonjs/NitroModules.js +24 -0
  74. package/lib/commonjs/NitroModules.js.map +1 -1
  75. package/lib/commonjs/package.json +1 -0
  76. package/lib/module/AnyMap.js +1 -1
  77. package/lib/module/HybridObject.js +1 -1
  78. package/lib/module/ModuleNotFoundError.js +2 -0
  79. package/lib/module/ModuleNotFoundError.js.map +1 -1
  80. package/lib/module/NativeNitroModules.js +2 -0
  81. package/lib/module/NativeNitroModules.js.map +1 -1
  82. package/lib/module/NativeNitroModules.web.js +2 -0
  83. package/lib/module/NativeNitroModules.web.js.map +1 -1
  84. package/lib/module/NitroModules.js +26 -0
  85. package/lib/module/NitroModules.js.map +1 -1
  86. package/lib/module/index.js +2 -0
  87. package/lib/module/index.js.map +1 -1
  88. package/lib/module/package.json +1 -0
  89. package/lib/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +13 -12
  91. package/src/AnyMap.ts +3 -0
  92. package/src/HybridObject.ts +15 -0
  93. package/src/NativeNitroModules.ts +5 -0
  94. package/src/NitroModules.ts +24 -0
  95. package/android/src/main/cpp/core/JHybridObject.cpp +0 -8
  96. package/cpp/templates/IsInPack.hpp +0 -21
  97. package/cpp/utils/NitroLogger.hpp +0 -58
  98. package/ios/utils/ClosureWrapper.swift +0 -45
@@ -38,8 +38,8 @@ using NativeInstanceId = std::type_index;
38
38
  */
39
39
  struct Prototype final {
40
40
  private:
41
- std::shared_ptr<Prototype> _base = nullptr;
42
41
  NativeInstanceId _instanceTypeId;
42
+ std::shared_ptr<Prototype> _base = nullptr;
43
43
  std::unordered_map<std::string, HybridFunction> _methods;
44
44
  std::unordered_map<std::string, HybridFunction> _getters;
45
45
  std::unordered_map<std::string, HybridFunction> _setters;
@@ -102,25 +102,6 @@ public:
102
102
  }
103
103
 
104
104
  public:
105
- /**
106
- * Registers the given C++ method as a Hybrid Method that can be called from JS, through the object's Prototype.
107
- * Example:
108
- * ```cpp
109
- * registerHybridMethod("sayHello", &MyObject::sayHello);
110
- * ```
111
- */
112
- template <typename Derived, typename ReturnType, typename... Args>
113
- inline void registerHybridMethod(std::string name, ReturnType (Derived::*method)(Args...)) {
114
- if (_getters.contains(name) || _setters.contains(name)) [[unlikely]] {
115
- throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a property with that name already exists!");
116
- }
117
- if (_methods.contains(name)) [[unlikely]] {
118
- throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a method with that name already exists!");
119
- }
120
-
121
- _methods.emplace(name, HybridFunction::createHybridFunction(name, method, FunctionType::METHOD));
122
- }
123
-
124
105
  /**
125
106
  * Registers the given C++ method as a property getter that can be called from JS, through the object's Prototype.
126
107
  * Example:
@@ -137,7 +118,7 @@ public:
137
118
  throw std::runtime_error("Cannot add Hybrid Property Getter \"" + name + "\" - a method with that name already exists!");
138
119
  }
139
120
 
140
- _getters.emplace(name, HybridFunction::createHybridFunction(name, method, FunctionType::GETTER));
121
+ _getters.emplace(name, HybridFunction::createHybridFunction(name, method, FunctionKind::GETTER));
141
122
  }
142
123
 
143
124
  /**
@@ -156,7 +137,47 @@ public:
156
137
  throw std::runtime_error("Cannot add Hybrid Property Setter \"" + name + "\" - a method with that name already exists!");
157
138
  }
158
139
 
159
- _setters.emplace(name, HybridFunction::createHybridFunction(name, method, FunctionType::SETTER));
140
+ _setters.emplace(name, HybridFunction::createHybridFunction(name, method, FunctionKind::SETTER));
141
+ }
142
+
143
+ /**
144
+ * Registers the given C++ method as a Hybrid Method that can be called from JS, through the object's Prototype.
145
+ * Example:
146
+ * ```cpp
147
+ * registerHybridMethod("sayHello", &MyObject::sayHello);
148
+ * ```
149
+ */
150
+ template <typename Derived, typename ReturnType, typename... Args>
151
+ inline void registerHybridMethod(std::string name, ReturnType (Derived::*method)(Args...)) {
152
+ if (_getters.contains(name) || _setters.contains(name)) [[unlikely]] {
153
+ throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a property with that name already exists!");
154
+ }
155
+ if (_methods.contains(name)) [[unlikely]] {
156
+ throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a method with that name already exists!");
157
+ }
158
+
159
+ _methods.emplace(name, HybridFunction::createHybridFunction(name, method, FunctionKind::METHOD));
160
+ }
161
+
162
+ /**
163
+ * Registers the given raw JSI C++ method as a Hybrid Method that can be called from JS, through the object's Prototype.
164
+ * Example:
165
+ * ```cpp
166
+ * registerRawHybridMethod("sayHello", &MyObject::sayHello);
167
+ * ```
168
+ */
169
+ template <typename Derived>
170
+ inline void registerRawHybridMethod(std::string name, size_t expectedArgumentsCount,
171
+ jsi::Value (Derived::*method)(jsi::Runtime& runtime, const jsi::Value& thisArg,
172
+ const jsi::Value* args, size_t count)) {
173
+ if (_getters.contains(name) || _setters.contains(name)) [[unlikely]] {
174
+ throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a property with that name already exists!");
175
+ }
176
+ if (_methods.contains(name)) [[unlikely]] {
177
+ throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a method with that name already exists!");
178
+ }
179
+
180
+ _methods.emplace(name, HybridFunction::createRawHybridFunction(name, expectedArgumentsCount, method));
160
181
  }
161
182
  };
162
183
 
@@ -29,9 +29,9 @@ std::vector<std::string> HybridObjectRegistry::getAllHybridObjectNames() {
29
29
  }
30
30
 
31
31
  void HybridObjectRegistry::registerHybridObjectConstructor(const std::string& hybridObjectName, HybridObjectConstructorFn&& constructorFn) {
32
- Logger::log(TAG, "Registering HybridObject \"%s\"...", hybridObjectName);
32
+ Logger::log(LogLevel::Info, TAG, "Registering HybridObject \"%s\"...", hybridObjectName.c_str());
33
33
  auto& map = HybridObjectRegistry::getRegistry();
34
- #if DEBUG
34
+ #ifndef NDEBUG
35
35
  if (map.contains(hybridObjectName)) [[unlikely]] {
36
36
  auto message =
37
37
  "HybridObject \"" + std::string(hybridObjectName) +
@@ -43,7 +43,7 @@ void HybridObjectRegistry::registerHybridObjectConstructor(const std::string& hy
43
43
  }
44
44
  #endif
45
45
  map.insert({hybridObjectName, std::move(constructorFn)});
46
- Logger::log(TAG, "Successfully registered HybridObject \"%s\"!", hybridObjectName);
46
+ Logger::log(LogLevel::Info, TAG, "Successfully registered HybridObject \"%s\"!", hybridObjectName.c_str());
47
47
  }
48
48
 
49
49
  std::shared_ptr<HybridObject> HybridObjectRegistry::createHybridObject(const std::string& hybridObjectName) {
@@ -57,7 +57,7 @@ std::shared_ptr<HybridObject> HybridObjectRegistry::createHybridObject(const std
57
57
  }
58
58
  std::shared_ptr<HybridObject> instance = fn->second();
59
59
 
60
- #if DEBUG
60
+ #ifndef NDEBUG
61
61
  if (instance == nullptr) [[unlikely]] {
62
62
  throw std::runtime_error("Failed to create HybridObject \"" + hybridObjectName +
63
63
  "\" - "
@@ -11,7 +11,7 @@ static constexpr auto GLOBAL_DISPATCHER_HOLDER_NAME = "__nitroDispatcher";
11
11
  std::unordered_map<jsi::Runtime*, std::weak_ptr<Dispatcher>> Dispatcher::_globalCache;
12
12
 
13
13
  void Dispatcher::installRuntimeGlobalDispatcher(jsi::Runtime& runtime, std::shared_ptr<Dispatcher> dispatcher) {
14
- Logger::log(TAG, "Installing global Dispatcher Holder into Runtime \"%s\"...", getRuntimeId(runtime));
14
+ Logger::log(LogLevel::Info, TAG, "Installing global Dispatcher Holder into Runtime \"%s\"...", getRuntimeId(runtime).c_str());
15
15
 
16
16
  // Store a weak reference in global cache
17
17
  _globalCache[&runtime] = std::weak_ptr(dispatcher);
@@ -33,14 +33,15 @@ std::shared_ptr<Dispatcher> Dispatcher::getRuntimeGlobalDispatcher(jsi::Runtime&
33
33
  }
34
34
  }
35
35
 
36
- Logger::log(TAG, "Unknown Runtime (%s), looking for Dispatcher through JSI global lookup...", getRuntimeId(runtime));
36
+ Logger::log(LogLevel::Warning, TAG, "Unknown Runtime (%s), looking for Dispatcher through JSI global lookup...",
37
+ getRuntimeId(runtime).c_str());
37
38
  jsi::Value dispatcherHolderValue = getRuntimeGlobalDispatcherHolder(runtime);
38
39
  jsi::Object dispatcherHolder = dispatcherHolderValue.getObject(runtime);
39
40
  return dispatcherHolder.getNativeState<Dispatcher>(runtime);
40
41
  }
41
42
 
42
43
  jsi::Value Dispatcher::getRuntimeGlobalDispatcherHolder(jsi::Runtime& runtime) {
43
- #if DEBUG
44
+ #ifndef NDEBUG
44
45
  if (!runtime.global().hasProperty(runtime, GLOBAL_DISPATCHER_HOLDER_NAME)) {
45
46
  throw std::runtime_error("Failed to get current Dispatcher - the global Dispatcher "
46
47
  "holder (global." +
@@ -12,7 +12,7 @@
12
12
  namespace margelo::nitro {
13
13
 
14
14
  ThreadPool::ThreadPool(const char* name, size_t numThreads) : _isAlive(true), _name(name) {
15
- Logger::log(TAG, "Creating ThreadPool \"%s\" with %i threads...", name, numThreads);
15
+ Logger::log(LogLevel::Info, TAG, "Creating ThreadPool \"%s\" with %i threads...", name, numThreads);
16
16
 
17
17
  for (size_t i = 0; i < numThreads; ++i) {
18
18
  std::string threadName = std::string(name) + "-" + std::to_string(i + 1);
@@ -56,7 +56,7 @@ void ThreadPool::run(std::function<void()>&& task) {
56
56
  }
57
57
 
58
58
  ThreadPool::~ThreadPool() {
59
- Logger::log(TAG, "Destroying ThreadPool \"%s\"...", _name);
59
+ Logger::log(LogLevel::Info, TAG, "Destroying ThreadPool \"%s\"...", _name);
60
60
 
61
61
  {
62
62
  // Lock and set `_isAlive` to false.
@@ -25,7 +25,7 @@ jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID&
25
25
  if (name == "install") {
26
26
  return jsi::Function::createFromHostFunction(
27
27
  runtime, jsi::PropNameID::forUtf8(runtime, "install"), 0,
28
- [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
28
+ [this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
29
29
  install(runtime);
30
30
  return jsi::Value::undefined();
31
31
  });
@@ -33,8 +33,8 @@ jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID&
33
33
  if (name == "createHybridObject") {
34
34
  return jsi::Function::createFromHostFunction(
35
35
  runtime, jsi::PropNameID::forUtf8(runtime, "createHybridObject"), 2,
36
- [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
37
- #if DEBUG
36
+ [this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
37
+ #ifndef NDEBUG
38
38
  if (count != 1 && count != 2) [[unlikely]] {
39
39
  throw jsi::JSError(runtime, "NitroModules.createHybridObject(..) expects 1 or 2 arguments, but " + std::to_string(count) +
40
40
  " were supplied!");
@@ -52,8 +52,8 @@ jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID&
52
52
  if (name == "hasHybridObject") {
53
53
  return jsi::Function::createFromHostFunction(
54
54
  runtime, jsi::PropNameID::forUtf8(runtime, "hasHybridObject"), 1,
55
- [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
56
- #if DEBUG
55
+ [this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
56
+ #ifndef NDEBUG
57
57
  if (count != 1) [[unlikely]] {
58
58
  throw jsi::JSError(runtime,
59
59
  "NitroModules.hasHybridObject(..) expects 1 argument (name), but received " + std::to_string(count) + "!");
@@ -65,8 +65,26 @@ jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID&
65
65
  }
66
66
  if (name == "getAllHybridObjectNames") {
67
67
  return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "getAllHybridObjectNames"), 0,
68
- [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args,
69
- size_t count) -> jsi::Value { return getAllHybridObjectNames(runtime); });
68
+ [this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args,
69
+ size_t count) -> jsi::Value { return getAllHybridObjectNames(runtime); });
70
+ }
71
+ if (name == "hasNativeState") {
72
+ return jsi::Function::createFromHostFunction(
73
+ runtime, jsi::PropNameID::forUtf8(runtime, "hasNativeState"), 1,
74
+ [](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
75
+ jsi::Object object = args[0].asObject(runtime);
76
+ bool has = object.hasNativeState(runtime) && object.getNativeState(runtime) != nullptr;
77
+ return jsi::Value(has);
78
+ });
79
+ }
80
+ if (name == "removeNativeState") {
81
+ return jsi::Function::createFromHostFunction(
82
+ runtime, jsi::PropNameID::forUtf8(runtime, "removeNativeState"), 1,
83
+ [](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
84
+ jsi::Object object = args[0].asObject(runtime);
85
+ object.setNativeState(runtime, nullptr);
86
+ return jsi::Value::undefined();
87
+ });
70
88
  }
71
89
 
72
90
  return jsi::Value::undefined();
@@ -80,7 +98,7 @@ void NativeNitroModules::install(jsi::Runtime& runtime) {
80
98
  }
81
99
 
82
100
  jsi::Value NativeNitroModules::createHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName,
83
- const std::optional<jsi::Object>& args) {
101
+ const std::optional<jsi::Object>&) {
84
102
  auto name = hybridObjectName.utf8(runtime);
85
103
  // TODO: Pass args? Do we need that?
86
104
  auto hybridObject = HybridObjectRegistry::createHybridObject(name.c_str());
@@ -4,4 +4,5 @@
4
4
 
5
5
  #pragma once
6
6
 
7
+ // Forward include, because in react-native they use `.h` instead of `.hpp`
7
8
  #include "NativeNitroModules.hpp"
@@ -22,7 +22,9 @@ public:
22
22
  public:
23
23
  jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& propName) override;
24
24
 
25
+ // Setup
25
26
  void install(jsi::Runtime& runtime);
27
+ // Hybrid Objects stuff
26
28
  jsi::Value createHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName, const std::optional<jsi::Object>& args);
27
29
  jsi::Value hasHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName);
28
30
  jsi::Value getAllHybridObjectNames(jsi::Runtime& runtime);
@@ -71,6 +71,20 @@ public:
71
71
  return name;
72
72
  }
73
73
 
74
+ /**
75
+ * Get a friendly name of the type `T` (if possible, demangled), without any namespaces
76
+ */
77
+ template <typename T>
78
+ static inline std::string getFriendlyTypenameNoNamespace() {
79
+ std::string friendly = getFriendlyTypename<T>();
80
+ size_t lastColon = friendly.rfind(':');
81
+ if (lastColon == std::string::npos) {
82
+ // Type does not have any namespace (:), just return as is.
83
+ return friendly;
84
+ }
85
+ return friendly.substr(lastColon + 1);
86
+ }
87
+
74
88
  template <typename... Types>
75
89
  static inline std::string getFriendlyTypenames() {
76
90
  std::ostringstream stream;
@@ -0,0 +1,91 @@
1
+ //
2
+ // AnyMapHolder.hpp
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 20.08.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "AnyMap.hpp"
11
+
12
+ namespace margelo::nitro {
13
+
14
+ using TSharedMap = std::shared_ptr<AnyMap>;
15
+
16
+ inline AnyValue create_AnyValue() {
17
+ return AnyValue{std::monostate{}};
18
+ }
19
+ inline AnyValue create_AnyValue(bool boolValue) {
20
+ return AnyValue{boolValue};
21
+ }
22
+ inline AnyValue create_AnyValue(double doubleValue) {
23
+ return AnyValue{doubleValue};
24
+ }
25
+ inline AnyValue create_AnyValue(int64_t bigintValue) {
26
+ return AnyValue{bigintValue};
27
+ }
28
+ inline AnyValue create_AnyValue(const std::string& stringValue) {
29
+ return AnyValue{stringValue};
30
+ }
31
+ inline AnyValue create_AnyValue(const AnyArray& arrayValue) {
32
+ return AnyValue{arrayValue};
33
+ }
34
+ inline AnyValue create_AnyValue(const AnyObject& objectValue) {
35
+ return AnyValue{objectValue};
36
+ }
37
+
38
+ inline bool is_AnyValue_null(const AnyValue& value) {
39
+ return std::holds_alternative<std::monostate>(value);
40
+ }
41
+ inline bool is_AnyValue_bool(const AnyValue& value) {
42
+ return std::holds_alternative<bool>(value);
43
+ }
44
+ inline bool is_AnyValue_number(const AnyValue& value) {
45
+ return std::holds_alternative<double>(value);
46
+ }
47
+ inline bool is_AnyValue_bigint(const AnyValue& value) {
48
+ return std::holds_alternative<int64_t>(value);
49
+ }
50
+ inline bool is_AnyValue_string(const AnyValue& value) {
51
+ return std::holds_alternative<std::string>(value);
52
+ }
53
+ inline bool is_AnyValue_AnyArray(const AnyValue& value) {
54
+ return std::holds_alternative<AnyArray>(value);
55
+ }
56
+ inline bool is_AnyValue_AnyObject(const AnyValue& value) {
57
+ return std::holds_alternative<AnyObject>(value);
58
+ }
59
+
60
+ inline std::monostate get_AnyValue_null(const AnyValue& value) {
61
+ return std::get<std::monostate>(value);
62
+ }
63
+ inline bool get_AnyValue_bool(const AnyValue& value) {
64
+ return std::get<bool>(value);
65
+ }
66
+ inline double get_AnyValue_number(const AnyValue& value) {
67
+ return std::get<double>(value);
68
+ }
69
+ inline int64_t get_AnyValue_bigint(const AnyValue& value) {
70
+ return std::get<int64_t>(value);
71
+ }
72
+ inline std::string get_AnyValue_string(const AnyValue& value) {
73
+ return std::get<std::string>(value);
74
+ }
75
+ inline AnyArray get_AnyValue_AnyArray(const AnyValue& value) {
76
+ return std::get<AnyArray>(value);
77
+ }
78
+ inline AnyObject get_AnyValue_AnyObject(const AnyValue& value) {
79
+ return std::get<AnyObject>(value);
80
+ }
81
+
82
+ inline std::vector<std::string> getAnyObjectKeys(const AnyObject& object) {
83
+ std::vector<std::string> keys;
84
+ keys.reserve(object.size());
85
+ for (const auto& entry : object) {
86
+ keys.push_back(entry.first);
87
+ }
88
+ return keys;
89
+ }
90
+
91
+ } // namespace margelo::nitro
@@ -0,0 +1,316 @@
1
+ //
2
+ // AnyMapHolder.swift
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 20.08.24.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ /**
11
+ * Represents any value representable by the `AnyMap`.
12
+ * Note: Arrays are currently not implemented due to a Swift compiler bug https://github.com/swiftlang/swift/issues/75994
13
+ */
14
+ public enum AnyValue {
15
+ case null
16
+ case number(Double)
17
+ case bool(Bool)
18
+ case bigint(Int64)
19
+ case string(String)
20
+ case object(Dictionary<String, AnyValue>)
21
+
22
+ static func create(_ value: margelo.nitro.AnyValue) -> AnyValue {
23
+ if margelo.nitro.is_AnyValue_null(value) {
24
+ return .null
25
+ } else if margelo.nitro.is_AnyValue_bool(value) {
26
+ return .bool(margelo.nitro.get_AnyValue_bool(value))
27
+ } else if margelo.nitro.is_AnyValue_number(value) {
28
+ return .number(margelo.nitro.get_AnyValue_number(value))
29
+ } else if margelo.nitro.is_AnyValue_bigint(value) {
30
+ return .bigint(margelo.nitro.get_AnyValue_bigint(value))
31
+ } else if margelo.nitro.is_AnyValue_string(value) {
32
+ return .string(margelo.nitro.get_AnyValue_string(value).toSwift())
33
+ } else if margelo.nitro.is_AnyValue_AnyObject(value) {
34
+ return .object(margelo.nitro.get_AnyValue_AnyObject(value).toSwift())
35
+ } else {
36
+ fatalError("AnyValue has unknown type!")
37
+ }
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Represents an `AnyMap` that can be passed to Swift.
43
+ */
44
+ public class AnyMapHolder {
45
+ let _cppPart: margelo.nitro.TSharedMap
46
+
47
+ public var cppPart: margelo.nitro.TSharedMap {
48
+ return _cppPart
49
+ }
50
+
51
+ public init() {
52
+ _cppPart = margelo.nitro.AnyMap.make()
53
+ }
54
+
55
+ public init(withPreallocatedSize size: Int) {
56
+ _cppPart = margelo.nitro.AnyMap.make(size)
57
+ }
58
+
59
+ public init(withCppPart cppPart: margelo.nitro.TSharedMap) {
60
+ _cppPart = cppPart
61
+ }
62
+
63
+ // pragma MARK: Common Operations
64
+
65
+ /**
66
+ * Returns whether the given key exists in the map.
67
+ */
68
+ public func contains(key: String) -> Bool {
69
+ return _cppPart.pointee.contains(std.string(key))
70
+ }
71
+
72
+ /**
73
+ * Removes the given key from the map.
74
+ */
75
+ public func remove(key: String) {
76
+ _cppPart.pointee.remove(std.string(key))
77
+ }
78
+
79
+ /**
80
+ * Removes all keys in this map.
81
+ */
82
+ public func clear() {
83
+ _cppPart.pointee.clear()
84
+ }
85
+
86
+ // pragma MARK: Getters
87
+
88
+ /**
89
+ * Gets the double value at the given key.
90
+ * If no value exists at the given key, or if it is not a double,
91
+ * this function throws.
92
+ */
93
+ public func getDouble(key: String) -> Double {
94
+ return _cppPart.pointee.getDouble(std.string(key))
95
+ }
96
+
97
+ /**
98
+ * Gets the double value at the given key.
99
+ * If no value exists at the given key, or if it is not a double,
100
+ * this function throws.
101
+ */
102
+ public func getBoolean(key: String) -> Bool {
103
+ return _cppPart.pointee.getBoolean(std.string(key))
104
+ }
105
+
106
+ /**
107
+ * Gets the double value at the given key.
108
+ * If no value exists at the given key, or if it is not a double,
109
+ * this function throws.
110
+ */
111
+ public func getBigInt(key: String) -> Int64 {
112
+ return _cppPart.pointee.getBigInt(std.string(key))
113
+ }
114
+
115
+ /**
116
+ * Gets the double value at the given key.
117
+ * If no value exists at the given key, or if it is not a double,
118
+ * this function throws.
119
+ */
120
+ public func getString(key: String) -> String {
121
+ let value = _cppPart.pointee.getString(std.string(key))
122
+ return String(value)
123
+ }
124
+
125
+ /**
126
+ * Gets the double value at the given key.
127
+ * If no value exists at the given key, or if it is not a double,
128
+ * this function throws.
129
+ */
130
+ public func getObject(key: String) -> Dictionary<String, AnyValue> {
131
+ let value = _cppPart.pointee.getObject(std.string(key))
132
+ return value.toSwift()
133
+ }
134
+
135
+ // pragma MARK: Setters
136
+
137
+ /**
138
+ * Set the given key to `null`.
139
+ */
140
+ public func setNull(key: String) {
141
+ _cppPart.pointee.setNull(std.string(key))
142
+ }
143
+
144
+ /**
145
+ * Set the given key to the given double value.
146
+ */
147
+ public func setDouble(key: String, value: Double) {
148
+ _cppPart.pointee.setDouble(std.string(key), value)
149
+ }
150
+
151
+ /**
152
+ * Set the given key to the given boolean value.
153
+ */
154
+ public func setBoolean(key: String, value: Bool) {
155
+ _cppPart.pointee.setBoolean(std.string(key), value)
156
+ }
157
+
158
+ /**
159
+ * Set the given key to the given bigint value.
160
+ */
161
+ public func setBigInt(key: String, value: Int64) {
162
+ _cppPart.pointee.setBigInt(std.string(key), value)
163
+ }
164
+
165
+ /**
166
+ * Set the given key to the given string value.
167
+ */
168
+ public func setString(key: String, value: String) {
169
+ _cppPart.pointee.setString(std.string(key), std.string(value))
170
+ }
171
+
172
+ /**
173
+ * Set the given key to the given object value.
174
+ */
175
+ public func setObject(key: String, value: Dictionary<String, AnyValue>) {
176
+ _cppPart.pointee.setObject(std.string(key), margelo.nitro.AnyObject.create(value))
177
+ }
178
+
179
+ // pragma MARK: Is Getters
180
+
181
+ /**
182
+ * Gets whether the given `key` is holding a null value, or not.
183
+ */
184
+ public func isNull(key: String) -> Bool {
185
+ return _cppPart.pointee.isNull(std.string(key))
186
+ }
187
+
188
+ /**
189
+ * Gets whether the given `key` is holding a double value, or not.
190
+ */
191
+ public func isDouble(key: String) -> Bool {
192
+ return _cppPart.pointee.isDouble(std.string(key))
193
+ }
194
+
195
+ /**
196
+ * Gets whether the given `key` is holding a boolean value, or not.
197
+ */
198
+ public func isBool(key: String) -> Bool {
199
+ return _cppPart.pointee.isBoolean(std.string(key))
200
+ }
201
+
202
+ /**
203
+ * Gets whether the given `key` is holding a bigint value, or not.
204
+ */
205
+ public func isBigInt(key: String) -> Bool {
206
+ return _cppPart.pointee.isBigInt(std.string(key))
207
+ }
208
+
209
+ /**
210
+ * Gets whether the given `key` is holding a string value, or not.
211
+ */
212
+ public func isString(key: String) -> Bool {
213
+ return _cppPart.pointee.isString(std.string(key))
214
+ }
215
+
216
+ /**
217
+ * Gets whether the given `key` is holding a object value, or not.
218
+ */
219
+ public func isObject(key: String) -> Bool {
220
+ return _cppPart.pointee.isObject(std.string(key))
221
+ }
222
+ }
223
+
224
+ // pragma MARK: margelo.nitro.AnyValue extension
225
+
226
+ extension margelo.nitro.AnyValue {
227
+ static func create(_ value: AnyValue) -> margelo.nitro.AnyValue {
228
+ switch value {
229
+ case .null:
230
+ return create()
231
+ case .bool(let bool):
232
+ return create(bool)
233
+ case .number(let number):
234
+ return create(number)
235
+ case .bigint(let bigint):
236
+ return create(bigint)
237
+ case .string(let string):
238
+ return create(string)
239
+ case .object(let object):
240
+ return create(object)
241
+ }
242
+ }
243
+ static func create() -> margelo.nitro.AnyValue {
244
+ return margelo.nitro.create_AnyValue()
245
+ }
246
+ static func create(_ value: Bool) -> margelo.nitro.AnyValue {
247
+ return margelo.nitro.create_AnyValue(value)
248
+ }
249
+ static func create(_ value: Double) -> margelo.nitro.AnyValue {
250
+ return margelo.nitro.create_AnyValue(value)
251
+ }
252
+ static func create(_ value: Int64) -> margelo.nitro.AnyValue {
253
+ return margelo.nitro.create_AnyValue(value)
254
+ }
255
+ static func create(_ value: String) -> margelo.nitro.AnyValue {
256
+ return margelo.nitro.create_AnyValue(std.string(value))
257
+ }
258
+ static func create(_ value: [AnyValue]) -> margelo.nitro.AnyValue {
259
+ return margelo.nitro.create_AnyValue(margelo.nitro.AnyArray.create(value))
260
+ }
261
+ static func create(_ value: Dictionary<String, AnyValue>) -> margelo.nitro.AnyValue {
262
+ return margelo.nitro.create_AnyValue(margelo.nitro.AnyObject.create(value))
263
+ }
264
+ }
265
+
266
+ // pragma MARK: std.string extension
267
+
268
+ extension std.string {
269
+ func toSwift() -> String {
270
+ return String(self)
271
+ }
272
+ }
273
+
274
+ // pragma MARK: margelo.nitro.AnyArray extension
275
+
276
+ extension margelo.nitro.AnyArray {
277
+ static func create(_ array: [AnyValue]) -> margelo.nitro.AnyArray {
278
+ var vector = margelo.nitro.AnyArray()
279
+ vector.reserve(array.count)
280
+ for value in array {
281
+ vector.push_back(margelo.nitro.AnyValue.create(value))
282
+ }
283
+ return vector
284
+ }
285
+
286
+ func toSwift() -> [AnyValue] {
287
+ var array: [AnyValue] = []
288
+ array.reserveCapacity(self.size())
289
+ for value in self {
290
+ array.append(AnyValue.create(value))
291
+ }
292
+ return array
293
+ }
294
+ }
295
+
296
+ // pragma MARK: margelo.nitro.AnyObject extension
297
+
298
+ extension margelo.nitro.AnyObject {
299
+ static func create(_ dictionary: Dictionary<String, AnyValue>) -> margelo.nitro.AnyObject {
300
+ var object = margelo.nitro.AnyObject()
301
+ object.reserve(dictionary.count)
302
+ for (key, value) in dictionary {
303
+ object[std.string(key)] = margelo.nitro.AnyValue.create(value)
304
+ }
305
+ return object
306
+ }
307
+
308
+ func toSwift() -> Dictionary<String, AnyValue> {
309
+ let keys = margelo.nitro.getAnyObjectKeys(self)
310
+ var dictionary = Dictionary<String, AnyValue>(minimumCapacity: keys.size())
311
+ for key in keys {
312
+
313
+ }
314
+ return dictionary
315
+ }
316
+ }