react-native-quick-crypto 0.2.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.
- package/LICENSE +21 -0
- package/README.md +84 -0
- package/android/.DS_Store +0 -0
- package/android/CMakeLists.txt +117 -0
- package/android/build.gradle +367 -0
- package/android/gradle/.DS_Store +0 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/android/gradle.properties +6 -0
- package/android/gradlew +183 -0
- package/android/gradlew.bat +100 -0
- package/android/src/.DS_Store +0 -0
- package/android/src/main/.DS_Store +0 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/cpp/cpp-adapter.cpp +60 -0
- package/android/src/main/java/.DS_Store +0 -0
- package/android/src/main/java/com/.DS_Store +0 -0
- package/android/src/main/java/com/reactnativequickcrypto/QuickCryptoModule.java +70 -0
- package/android/src/main/java/com/reactnativequickcrypto/QuickCryptoPackage.java +26 -0
- package/cpp/.DS_Store +0 -0
- package/cpp/Cipher/MGLCipherHostObject.cpp +632 -0
- package/cpp/Cipher/MGLCipherHostObject.h +90 -0
- package/cpp/Cipher/MGLCreateCipherInstaller.cpp +74 -0
- package/cpp/Cipher/MGLCreateCipherInstaller.h +17 -0
- package/cpp/Cipher/MGLCreateDecipherInstaller.cpp +74 -0
- package/cpp/Cipher/MGLCreateDecipherInstaller.h +17 -0
- package/cpp/HMAC/MGLHmacHostObject.cpp +95 -0
- package/cpp/HMAC/MGLHmacHostObject.h +39 -0
- package/cpp/HMAC/MGLHmacInstaller.cpp +43 -0
- package/cpp/HMAC/MGLHmacInstaller.h +20 -0
- package/cpp/Hash/MGLHashHostObject.cpp +147 -0
- package/cpp/Hash/MGLHashHostObject.h +53 -0
- package/cpp/Hash/MGLHashInstaller.cpp +46 -0
- package/cpp/Hash/MGLHashInstaller.h +20 -0
- package/cpp/JSIUtils/MGLJSIMacros.h +37 -0
- package/cpp/JSIUtils/MGLSmartHostObject.cpp +43 -0
- package/cpp/JSIUtils/MGLSmartHostObject.h +46 -0
- package/cpp/JSIUtils/MGLThreadAwareHostObject.cpp +24 -0
- package/cpp/JSIUtils/MGLThreadAwareHostObject.h +43 -0
- package/cpp/JSIUtils/MGLTypedArray.cpp +325 -0
- package/cpp/JSIUtils/MGLTypedArray.h +160 -0
- package/cpp/MGLQuickCryptoHostObject.cpp +64 -0
- package/cpp/MGLQuickCryptoHostObject.h +30 -0
- package/cpp/Random/MGLRandomHostObject.cpp +89 -0
- package/cpp/Random/MGLRandomHostObject.h +27 -0
- package/cpp/Utils/MGLDispatchQueue.cpp +75 -0
- package/cpp/Utils/MGLDispatchQueue.h +55 -0
- package/cpp/Utils/logs.h +38 -0
- package/cpp/fastpbkdf2/MGLPbkdf2HostObject.cpp +164 -0
- package/cpp/fastpbkdf2/MGLPbkdf2HostObject.h +29 -0
- package/cpp/fastpbkdf2/fastpbkdf2.c +352 -0
- package/cpp/fastpbkdf2/fastpbkdf2.h +68 -0
- package/ios/.DS_Store +0 -0
- package/ios/QuickCrypto.xcodeproj/project.pbxproj +274 -0
- package/ios/QuickCryptoModule.h +5 -0
- package/ios/QuickCryptoModule.mm +42 -0
- package/lib/.DS_Store +0 -0
- package/lib/commonjs/Cipher.js +293 -0
- package/lib/commonjs/Cipher.js.map +1 -0
- package/lib/commonjs/Hash.js +102 -0
- package/lib/commonjs/Hash.js.map +1 -0
- package/lib/commonjs/Hmac.js +104 -0
- package/lib/commonjs/Hmac.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/Cipher.js +6 -0
- package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js +61 -0
- package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/hash.js +2 -0
- package/lib/commonjs/NativeQuickCrypto/hash.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/hmac.js +2 -0
- package/lib/commonjs/NativeQuickCrypto/hmac.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/pbkdf2.js +2 -0
- package/lib/commonjs/NativeQuickCrypto/pbkdf2.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/random.js +2 -0
- package/lib/commonjs/NativeQuickCrypto/random.js.map +1 -0
- package/lib/commonjs/QuickCrypto.js +35 -0
- package/lib/commonjs/QuickCrypto.js.map +1 -0
- package/lib/commonjs/Utils.js +152 -0
- package/lib/commonjs/Utils.js.map +1 -0
- package/lib/commonjs/index.js +19 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/pbkdf2.js +64 -0
- package/lib/commonjs/pbkdf2.js.map +1 -0
- package/lib/commonjs/random.js +213 -0
- package/lib/commonjs/random.js.map +1 -0
- package/lib/module/Cipher.js +287 -0
- package/lib/module/Cipher.js.map +1 -0
- package/lib/module/Hash.js +87 -0
- package/lib/module/Hash.js.map +1 -0
- package/lib/module/Hmac.js +90 -0
- package/lib/module/Hmac.js.map +1 -0
- package/lib/module/NativeQuickCrypto/Cipher.js +2 -0
- package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -0
- package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js +53 -0
- package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -0
- package/lib/module/NativeQuickCrypto/hash.js +2 -0
- package/lib/module/NativeQuickCrypto/hash.js.map +1 -0
- package/lib/module/NativeQuickCrypto/hmac.js +2 -0
- package/lib/module/NativeQuickCrypto/hmac.js.map +1 -0
- package/lib/module/NativeQuickCrypto/pbkdf2.js +2 -0
- package/lib/module/NativeQuickCrypto/pbkdf2.js.map +1 -0
- package/lib/module/NativeQuickCrypto/random.js +2 -0
- package/lib/module/NativeQuickCrypto/random.js.map +1 -0
- package/lib/module/QuickCrypto.js +18 -0
- package/lib/module/QuickCrypto.js.map +1 -0
- package/lib/module/Utils.js +131 -0
- package/lib/module/Utils.js.map +1 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/pbkdf2.js +51 -0
- package/lib/module/pbkdf2.js.map +1 -0
- package/lib/module/random.js +190 -0
- package/lib/module/random.js.map +1 -0
- package/lib/typescript/Cipher.d.ts +30 -0
- package/lib/typescript/Hash.d.ts +44 -0
- package/lib/typescript/Hmac.d.ts +37 -0
- package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +22 -0
- package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +19 -0
- package/lib/typescript/NativeQuickCrypto/hash.d.ts +6 -0
- package/lib/typescript/NativeQuickCrypto/hmac.d.ts +5 -0
- package/lib/typescript/NativeQuickCrypto/pbkdf2.d.ts +4 -0
- package/lib/typescript/NativeQuickCrypto/random.d.ts +4 -0
- package/lib/typescript/QuickCrypto.d.ts +31 -0
- package/lib/typescript/Utils.d.ts +13 -0
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/pbkdf2.d.ts +9 -0
- package/lib/typescript/random.d.ts +20 -0
- package/package.json +168 -0
- package/react-native-quick-crypto.podspec +44 -0
- package/src/Cipher.ts +322 -0
- package/src/Hash.ts +98 -0
- package/src/Hmac.ts +107 -0
- package/src/NativeQuickCrypto/Cipher.ts +25 -0
- package/src/NativeQuickCrypto/NativeQuickCrypto.ts +79 -0
- package/src/NativeQuickCrypto/hash.ts +10 -0
- package/src/NativeQuickCrypto/hmac.ts +9 -0
- package/src/NativeQuickCrypto/pbkdf2.ts +16 -0
- package/src/NativeQuickCrypto/random.ts +12 -0
- package/src/QuickCrypto.ts +23 -0
- package/src/Utils.ts +151 -0
- package/src/index.ts +1 -0
- package/src/pbkdf2.ts +96 -0
- package/src/random.ts +277 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HMAC-JSI-Installer.m
|
|
3
|
+
// PinkPanda
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 31.10.21.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "MGLHashInstaller.h"
|
|
9
|
+
|
|
10
|
+
#include <openssl/hmac.h>
|
|
11
|
+
|
|
12
|
+
#include <memory>
|
|
13
|
+
|
|
14
|
+
#ifdef ANDROID
|
|
15
|
+
#include "JSIUtils/MGLJSIMacros.h"
|
|
16
|
+
#else
|
|
17
|
+
#include "MGLJSIMacros.h"
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
#include "MGLHashHostObject.h"
|
|
21
|
+
|
|
22
|
+
using namespace facebook;
|
|
23
|
+
|
|
24
|
+
namespace margelo {
|
|
25
|
+
|
|
26
|
+
FieldDefinition getHashFieldDefinition(
|
|
27
|
+
std::shared_ptr<react::CallInvoker> jsCallInvoker,
|
|
28
|
+
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue) {
|
|
29
|
+
// createHash(hashAlgorithm: 'sha1' | 'sha256' | 'sha512')
|
|
30
|
+
return HOST_LAMBDA("createHash", {
|
|
31
|
+
if (count != 1 && count != 2) {
|
|
32
|
+
throw jsi::JSError(runtime, "createHmac(..) expects 1-2 arguments!");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
auto hashAlgorithm = arguments[0].asString(runtime).utf8(runtime);
|
|
36
|
+
int md_len = -1;
|
|
37
|
+
if (!arguments[1].isUndefined()) {
|
|
38
|
+
md_len = (int)arguments[1].asNumber();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
auto hostObject = std::make_shared<MGLHashHostObject>(
|
|
42
|
+
hashAlgorithm, md_len, jsCallInvoker, workerQueue);
|
|
43
|
+
return jsi::Object::createFromHostObject(runtime, hostObject);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
} // namespace margelo
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#include <jsi/jsi.h>
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
|
|
5
|
+
#ifdef ANDROID
|
|
6
|
+
#include "JSIUtils/MGLSmartHostObject.h"
|
|
7
|
+
#else
|
|
8
|
+
#include "MGLSmartHostObject.h"
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
namespace margelo {
|
|
12
|
+
namespace jsi = facebook::jsi;
|
|
13
|
+
|
|
14
|
+
/// It's signature is:
|
|
15
|
+
/// createHmac(hashAlgorithm: 'sha1' | 'sha256' | 'sha512',
|
|
16
|
+
/// key: string): HMAC
|
|
17
|
+
FieldDefinition getHashFieldDefinition(
|
|
18
|
+
std::shared_ptr<react::CallInvoker> jsCallInvoker,
|
|
19
|
+
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
|
|
20
|
+
} // namespace margelo
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by Szymon on 24/02/2022.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#ifndef MGL_JSIMACROS_H
|
|
6
|
+
#define MGL_JSIMACROS_H
|
|
7
|
+
|
|
8
|
+
#include <utility>
|
|
9
|
+
|
|
10
|
+
// if you want to create a new marco use (https://godbolt.org) provide flag -E
|
|
11
|
+
// in right panel
|
|
12
|
+
|
|
13
|
+
#define HOST_LAMBDA(name, body) HOST_LAMBDA_CAP(name, [=], body)
|
|
14
|
+
|
|
15
|
+
#define HOST_LAMBDA_CAP(name, capture, body) \
|
|
16
|
+
std::make_pair( \
|
|
17
|
+
name, capture(jsi::Runtime &runtime) { \
|
|
18
|
+
const auto func = \
|
|
19
|
+
capture(jsi::Runtime & runtime, const jsi::Value &thisValue, \
|
|
20
|
+
const jsi::Value *arguments, size_t count) \
|
|
21
|
+
->jsi::Value body; \
|
|
22
|
+
auto propNameID = jsi::PropNameID::forAscii(runtime, name); \
|
|
23
|
+
return jsi::Function::createFromHostFunction(runtime, propNameID, 0, \
|
|
24
|
+
func); \
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
#define JSI_VALUE(name, body) JSI_VALUE_CAP(name, [=], body)
|
|
28
|
+
|
|
29
|
+
#define JSI_VALUE_CAP(name, capture, body) \
|
|
30
|
+
std::make_pair(name, capture(jsi::Runtime &runtime) body)
|
|
31
|
+
|
|
32
|
+
#define JSIF(capture) \
|
|
33
|
+
capture(jsi::Runtime &runtime, const jsi::Value &thisValue, \
|
|
34
|
+
const jsi::Value *arguments, size_t count) \
|
|
35
|
+
->jsi::Value
|
|
36
|
+
|
|
37
|
+
#endif // MGL_JSIMACROS_H
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by Szymon on 24/02/2022.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#include "MGLSmartHostObject.h"
|
|
6
|
+
|
|
7
|
+
namespace margelo {
|
|
8
|
+
|
|
9
|
+
namespace jsi = facebook::jsi;
|
|
10
|
+
namespace react = facebook::react;
|
|
11
|
+
|
|
12
|
+
FieldDefinition buildPair(std::string name, jsi::HostFunctionType &&f) {
|
|
13
|
+
auto valueBuilder = [f, name](jsi::Runtime &runtime) {
|
|
14
|
+
const auto func = f;
|
|
15
|
+
auto propNameID = jsi::PropNameID::forAscii(runtime, name);
|
|
16
|
+
return jsi::Function::createFromHostFunction(runtime, propNameID, 0, func);
|
|
17
|
+
};
|
|
18
|
+
return std::make_pair(name, valueBuilder);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
std::vector<jsi::PropNameID> MGLSmartHostObject::getPropertyNames(
|
|
22
|
+
jsi::Runtime &runtime) {
|
|
23
|
+
std::vector<jsi::PropNameID> propertyNames;
|
|
24
|
+
for (auto field : fields) {
|
|
25
|
+
propertyNames.push_back(jsi::PropNameID::forAscii(runtime, field.first));
|
|
26
|
+
}
|
|
27
|
+
return propertyNames;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// TODO(Szymon) maybe add memoization here
|
|
31
|
+
jsi::Value MGLSmartHostObject::get(jsi::Runtime &runtime,
|
|
32
|
+
const jsi::PropNameID &propNameId) {
|
|
33
|
+
auto name = propNameId.utf8(runtime);
|
|
34
|
+
for (auto field : fields) {
|
|
35
|
+
auto fieldName = field.first;
|
|
36
|
+
if (fieldName == name) {
|
|
37
|
+
return (field.second)(runtime);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return jsi::Value::undefined();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
} // namespace margelo
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by Szymon on 24/02/2022.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#ifndef MGL_SMARTHOSTOBJECT_H
|
|
6
|
+
#define MGL_SMARTHOSTOBJECT_H
|
|
7
|
+
|
|
8
|
+
#include <ReactCommon/TurboModuleUtils.h>
|
|
9
|
+
|
|
10
|
+
#include <memory>
|
|
11
|
+
#include <string>
|
|
12
|
+
#include <utility>
|
|
13
|
+
#include <vector>
|
|
14
|
+
|
|
15
|
+
#include "MGLJSIMacros.h"
|
|
16
|
+
#include "MGLThreadAwareHostObject.h"
|
|
17
|
+
|
|
18
|
+
namespace margelo {
|
|
19
|
+
|
|
20
|
+
namespace jsi = facebook::jsi;
|
|
21
|
+
namespace react = facebook::react;
|
|
22
|
+
|
|
23
|
+
typedef std::function<jsi::Value(jsi::Runtime &runtime)> JSIValueBuilder;
|
|
24
|
+
|
|
25
|
+
typedef std::pair<std::string, JSIValueBuilder> FieldDefinition;
|
|
26
|
+
|
|
27
|
+
FieldDefinition buildPair(std::string name, jsi::HostFunctionType &&f);
|
|
28
|
+
|
|
29
|
+
class JSI_EXPORT MGLSmartHostObject : public MGLThreadAwareHostObject {
|
|
30
|
+
public:
|
|
31
|
+
MGLSmartHostObject(std::shared_ptr<react::CallInvoker> jsCallInvoker,
|
|
32
|
+
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
|
|
33
|
+
: MGLThreadAwareHostObject(jsCallInvoker, workerQueue) {}
|
|
34
|
+
|
|
35
|
+
virtual ~MGLSmartHostObject() {}
|
|
36
|
+
|
|
37
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &runtime);
|
|
38
|
+
|
|
39
|
+
jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &propNameId);
|
|
40
|
+
|
|
41
|
+
std::vector<std::pair<std::string, JSIValueBuilder>> fields;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
} // namespace margelo
|
|
45
|
+
|
|
46
|
+
#endif // MGL_SMARTHOSTOBJECT_H
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by Szymon on 24/02/2022.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#include "MGLThreadAwareHostObject.h"
|
|
6
|
+
|
|
7
|
+
#include <utility>
|
|
8
|
+
|
|
9
|
+
namespace margelo {
|
|
10
|
+
|
|
11
|
+
namespace jsi = facebook::jsi;
|
|
12
|
+
|
|
13
|
+
void MGLThreadAwareHostObject::runOnWorkerThread(std::function<void()> &&job) {
|
|
14
|
+
this->dispatchQueue->dispatch(job);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void MGLThreadAwareHostObject::runOnJSThread(std::function<void()> &&job) {
|
|
18
|
+
auto callInvoker = this->weakJsCallInvoker.lock();
|
|
19
|
+
if (callInvoker != nullptr) {
|
|
20
|
+
callInvoker->invokeAsync(std::move(job));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
} // namespace margelo
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by Szymon on 24/02/2022.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#ifndef MGL_THREADAWAREHOSTOBJECT_H
|
|
6
|
+
#define MGL_THREADAWAREHOSTOBJECT_H
|
|
7
|
+
|
|
8
|
+
#include <ReactCommon/CallInvoker.h>
|
|
9
|
+
#include <jsi/jsi.h>
|
|
10
|
+
|
|
11
|
+
#include <memory>
|
|
12
|
+
|
|
13
|
+
#ifdef ONANDROID
|
|
14
|
+
#include "Utils/MGLDispatchQueue.h"
|
|
15
|
+
#else
|
|
16
|
+
#include "../Utils/MGLDispatchQueue.h"
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
namespace margelo {
|
|
20
|
+
|
|
21
|
+
namespace jsi = facebook::jsi;
|
|
22
|
+
namespace react = facebook::react;
|
|
23
|
+
|
|
24
|
+
class JSI_EXPORT MGLThreadAwareHostObject : public jsi::HostObject {
|
|
25
|
+
public:
|
|
26
|
+
explicit MGLThreadAwareHostObject(
|
|
27
|
+
std::shared_ptr<react::CallInvoker> jsCallInvoker,
|
|
28
|
+
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
|
|
29
|
+
: weakJsCallInvoker(jsCallInvoker), dispatchQueue(workerQueue) {}
|
|
30
|
+
|
|
31
|
+
virtual ~MGLThreadAwareHostObject() {}
|
|
32
|
+
|
|
33
|
+
void runOnWorkerThread(std::function<void(void)> &&job);
|
|
34
|
+
void runOnJSThread(std::function<void(void)> &&job);
|
|
35
|
+
|
|
36
|
+
protected:
|
|
37
|
+
std::weak_ptr<react::CallInvoker> weakJsCallInvoker;
|
|
38
|
+
std::shared_ptr<DispatchQueue::dispatch_queue> dispatchQueue;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
} // namespace margelo
|
|
42
|
+
|
|
43
|
+
#endif // MGL_THREADAWAREHOSTOBJECT_H
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
//
|
|
2
|
+
// TypedArray.cpp
|
|
3
|
+
// react-native-quick-crypto
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 31.10.21.
|
|
6
|
+
// Originally created by Expo (expo-gl)
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#include "MGLTypedArray.h"
|
|
10
|
+
|
|
11
|
+
#include <algorithm>
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <string>
|
|
14
|
+
#include <unordered_map>
|
|
15
|
+
|
|
16
|
+
template <MGLTypedArrayKind T>
|
|
17
|
+
using ContentType = typename typedArrayTypeMap<T>::type;
|
|
18
|
+
|
|
19
|
+
enum class Prop {
|
|
20
|
+
Buffer, // "buffer"
|
|
21
|
+
Constructor, // "constructor"
|
|
22
|
+
Name, // "name"
|
|
23
|
+
Proto, // "__proto__"
|
|
24
|
+
Length, // "length"
|
|
25
|
+
ByteLength, // "byteLength"
|
|
26
|
+
ByteOffset, // "offset"
|
|
27
|
+
IsView, // "isView"
|
|
28
|
+
ArrayBuffer, // "ArrayBuffer"
|
|
29
|
+
Int8Array, // "Int8Array"
|
|
30
|
+
Int16Array, // "Int16Array"
|
|
31
|
+
Int32Array, // "Int32Array"
|
|
32
|
+
Uint8Array, // "Uint8Array"
|
|
33
|
+
Uint8ClampedArray, // "Uint8ClampedArray"
|
|
34
|
+
Uint16Array, // "Uint16Array"
|
|
35
|
+
Uint32Array, // "Uint32Array"
|
|
36
|
+
Float32Array, // "Float32Array"
|
|
37
|
+
Float64Array, // "Float64Array"
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
class PropNameIDCache {
|
|
41
|
+
public:
|
|
42
|
+
const jsi::PropNameID &get(jsi::Runtime &runtime, Prop prop) {
|
|
43
|
+
if (!this->props[prop]) {
|
|
44
|
+
this->props[prop] =
|
|
45
|
+
std::make_unique<jsi::PropNameID>(createProp(runtime, prop));
|
|
46
|
+
}
|
|
47
|
+
return *(this->props[prop]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const jsi::PropNameID &getConstructorNameProp(jsi::Runtime &runtime,
|
|
51
|
+
MGLTypedArrayKind kind);
|
|
52
|
+
|
|
53
|
+
void invalidate() { props.erase(props.begin(), props.end()); }
|
|
54
|
+
|
|
55
|
+
private:
|
|
56
|
+
std::unordered_map<Prop, std::unique_ptr<jsi::PropNameID>> props;
|
|
57
|
+
|
|
58
|
+
jsi::PropNameID createProp(jsi::Runtime &runtime, Prop prop);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
PropNameIDCache propNameIDCache;
|
|
62
|
+
|
|
63
|
+
void invalidateJsiPropNameIDCache() { propNameIDCache.invalidate(); }
|
|
64
|
+
|
|
65
|
+
MGLTypedArrayKind getTypedArrayKindForName(const std::string &name);
|
|
66
|
+
|
|
67
|
+
MGLTypedArrayBase::MGLTypedArrayBase(jsi::Runtime &runtime, size_t size,
|
|
68
|
+
MGLTypedArrayKind kind)
|
|
69
|
+
: MGLTypedArrayBase(
|
|
70
|
+
runtime,
|
|
71
|
+
runtime.global()
|
|
72
|
+
.getProperty(runtime, propNameIDCache.getConstructorNameProp(
|
|
73
|
+
runtime, kind))
|
|
74
|
+
.asObject(runtime)
|
|
75
|
+
.asFunction(runtime)
|
|
76
|
+
.callAsConstructor(runtime, {static_cast<double>(size)})
|
|
77
|
+
.asObject(runtime)) {}
|
|
78
|
+
|
|
79
|
+
MGLTypedArrayBase::MGLTypedArrayBase(jsi::Runtime &runtime,
|
|
80
|
+
const jsi::Object &obj)
|
|
81
|
+
: jsi::Object(jsi::Value(runtime, obj).asObject(runtime)) {}
|
|
82
|
+
|
|
83
|
+
MGLTypedArrayKind MGLTypedArrayBase::getKind(jsi::Runtime &runtime) const {
|
|
84
|
+
auto constructorName =
|
|
85
|
+
this->getProperty(runtime,
|
|
86
|
+
propNameIDCache.get(runtime, Prop::Constructor))
|
|
87
|
+
.asObject(runtime)
|
|
88
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::Name))
|
|
89
|
+
.asString(runtime)
|
|
90
|
+
.utf8(runtime);
|
|
91
|
+
return getTypedArrayKindForName(constructorName);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
size_t MGLTypedArrayBase::size(jsi::Runtime &runtime) const {
|
|
95
|
+
return getProperty(runtime, propNameIDCache.get(runtime, Prop::Length))
|
|
96
|
+
.asNumber();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
size_t MGLTypedArrayBase::length(jsi::Runtime &runtime) const {
|
|
100
|
+
return getProperty(runtime, propNameIDCache.get(runtime, Prop::Length))
|
|
101
|
+
.asNumber();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
size_t MGLTypedArrayBase::byteLength(jsi::Runtime &runtime) const {
|
|
105
|
+
return getProperty(runtime, propNameIDCache.get(runtime, Prop::ByteLength))
|
|
106
|
+
.asNumber();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
size_t MGLTypedArrayBase::byteOffset(jsi::Runtime &runtime) const {
|
|
110
|
+
return getProperty(runtime, propNameIDCache.get(runtime, Prop::ByteOffset))
|
|
111
|
+
.asNumber();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
bool MGLTypedArrayBase::hasBuffer(jsi::Runtime &runtime) const {
|
|
115
|
+
auto buffer =
|
|
116
|
+
getProperty(runtime, propNameIDCache.get(runtime, Prop::Buffer));
|
|
117
|
+
return buffer.isObject() && buffer.asObject(runtime).isArrayBuffer(runtime);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
std::vector<uint8_t> MGLTypedArrayBase::toVector(jsi::Runtime &runtime) {
|
|
121
|
+
auto start = reinterpret_cast<uint8_t *>(getBuffer(runtime).data(runtime) +
|
|
122
|
+
byteOffset(runtime));
|
|
123
|
+
auto end = start + byteLength(runtime);
|
|
124
|
+
return std::vector<uint8_t>(start, end);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
jsi::ArrayBuffer MGLTypedArrayBase::getBuffer(jsi::Runtime &runtime) const {
|
|
128
|
+
auto buffer =
|
|
129
|
+
getProperty(runtime, propNameIDCache.get(runtime, Prop::Buffer));
|
|
130
|
+
if (buffer.isObject() && buffer.asObject(runtime).isArrayBuffer(runtime)) {
|
|
131
|
+
return buffer.asObject(runtime).getArrayBuffer(runtime);
|
|
132
|
+
} else {
|
|
133
|
+
throw std::runtime_error("no ArrayBuffer attached");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
bool isTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj) {
|
|
138
|
+
auto jsVal =
|
|
139
|
+
runtime.global()
|
|
140
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::ArrayBuffer))
|
|
141
|
+
.asObject(runtime)
|
|
142
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::IsView))
|
|
143
|
+
.asObject(runtime)
|
|
144
|
+
.asFunction(runtime)
|
|
145
|
+
.callWithThis(runtime, runtime.global(),
|
|
146
|
+
{jsi::Value(runtime, jsObj)});
|
|
147
|
+
if (jsVal.isBool()) {
|
|
148
|
+
return jsVal.getBool();
|
|
149
|
+
} else {
|
|
150
|
+
throw std::runtime_error("value is not a boolean");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
MGLTypedArrayBase getTypedArray(jsi::Runtime &runtime,
|
|
155
|
+
const jsi::Object &jsObj) {
|
|
156
|
+
auto jsVal =
|
|
157
|
+
runtime.global()
|
|
158
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::ArrayBuffer))
|
|
159
|
+
.asObject(runtime)
|
|
160
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::IsView))
|
|
161
|
+
.asObject(runtime)
|
|
162
|
+
.asFunction(runtime)
|
|
163
|
+
.callWithThis(runtime, runtime.global(),
|
|
164
|
+
{jsi::Value(runtime, jsObj)});
|
|
165
|
+
if (jsVal.isBool()) {
|
|
166
|
+
return MGLTypedArrayBase(runtime, jsObj);
|
|
167
|
+
} else {
|
|
168
|
+
throw std::runtime_error("value is not a boolean");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
std::vector<uint8_t> arrayBufferToVector(jsi::Runtime &runtime,
|
|
173
|
+
jsi::Object &jsObj) {
|
|
174
|
+
if (!jsObj.isArrayBuffer(runtime)) {
|
|
175
|
+
throw std::runtime_error("Object is not an ArrayBuffer");
|
|
176
|
+
}
|
|
177
|
+
auto jsArrayBuffer = jsObj.getArrayBuffer(runtime);
|
|
178
|
+
|
|
179
|
+
uint8_t *dataBlock = jsArrayBuffer.data(runtime);
|
|
180
|
+
size_t blockSize =
|
|
181
|
+
jsArrayBuffer
|
|
182
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::ByteLength))
|
|
183
|
+
.asNumber();
|
|
184
|
+
return std::vector<uint8_t>(dataBlock, dataBlock + blockSize);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
void arrayBufferUpdate(jsi::Runtime &runtime, jsi::ArrayBuffer &buffer,
|
|
188
|
+
std::vector<uint8_t> data, size_t offset) {
|
|
189
|
+
uint8_t *dataBlock = buffer.data(runtime);
|
|
190
|
+
size_t blockSize = buffer.size(runtime);
|
|
191
|
+
if (data.size() > blockSize) {
|
|
192
|
+
throw jsi::JSError(runtime, "ArrayBuffer is to small to fit data");
|
|
193
|
+
}
|
|
194
|
+
std::copy(data.begin(), data.end(), dataBlock + offset);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
template <MGLTypedArrayKind T>
|
|
198
|
+
MGLTypedArray<T>::MGLTypedArray(jsi::Runtime &runtime, size_t size)
|
|
199
|
+
: MGLTypedArrayBase(runtime, size, T) {}
|
|
200
|
+
|
|
201
|
+
template <MGLTypedArrayKind T>
|
|
202
|
+
MGLTypedArray<T>::MGLTypedArray(jsi::Runtime &runtime,
|
|
203
|
+
std::vector<ContentType<T>> data)
|
|
204
|
+
: MGLTypedArrayBase(runtime, data.size(), T) {
|
|
205
|
+
update(runtime, data);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
template <MGLTypedArrayKind T>
|
|
209
|
+
MGLTypedArray<T>::MGLTypedArray(MGLTypedArrayBase &&base)
|
|
210
|
+
: MGLTypedArrayBase(std::move(base)) {}
|
|
211
|
+
|
|
212
|
+
template <MGLTypedArrayKind T>
|
|
213
|
+
std::vector<ContentType<T>> MGLTypedArray<T>::toVector(jsi::Runtime &runtime) {
|
|
214
|
+
auto start = reinterpret_cast<ContentType<T> *>(
|
|
215
|
+
getBuffer(runtime).data(runtime) + byteOffset(runtime));
|
|
216
|
+
auto end = start + size(runtime);
|
|
217
|
+
return std::vector<ContentType<T>>(start, end);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
template <MGLTypedArrayKind T>
|
|
221
|
+
void MGLTypedArray<T>::update(jsi::Runtime &runtime,
|
|
222
|
+
const std::vector<ContentType<T>> &data) {
|
|
223
|
+
if (data.size() != size(runtime)) {
|
|
224
|
+
throw jsi::JSError(
|
|
225
|
+
runtime,
|
|
226
|
+
"TypedArray can only be updated with a vector of the same size");
|
|
227
|
+
}
|
|
228
|
+
uint8_t *rawData = getBuffer(runtime).data(runtime) + byteOffset(runtime);
|
|
229
|
+
std::copy(data.begin(), data.end(),
|
|
230
|
+
reinterpret_cast<ContentType<T> *>(rawData));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const jsi::PropNameID &PropNameIDCache::getConstructorNameProp(
|
|
234
|
+
jsi::Runtime &runtime, MGLTypedArrayKind kind) {
|
|
235
|
+
switch (kind) {
|
|
236
|
+
case MGLTypedArrayKind::Int8Array:
|
|
237
|
+
return get(runtime, Prop::Int8Array);
|
|
238
|
+
case MGLTypedArrayKind::Int16Array:
|
|
239
|
+
return get(runtime, Prop::Int16Array);
|
|
240
|
+
case MGLTypedArrayKind::Int32Array:
|
|
241
|
+
return get(runtime, Prop::Int32Array);
|
|
242
|
+
case MGLTypedArrayKind::Uint8Array:
|
|
243
|
+
return get(runtime, Prop::Uint8Array);
|
|
244
|
+
case MGLTypedArrayKind::Uint8ClampedArray:
|
|
245
|
+
return get(runtime, Prop::Uint8ClampedArray);
|
|
246
|
+
case MGLTypedArrayKind::Uint16Array:
|
|
247
|
+
return get(runtime, Prop::Uint16Array);
|
|
248
|
+
case MGLTypedArrayKind::Uint32Array:
|
|
249
|
+
return get(runtime, Prop::Uint32Array);
|
|
250
|
+
case MGLTypedArrayKind::Float32Array:
|
|
251
|
+
return get(runtime, Prop::Float32Array);
|
|
252
|
+
case MGLTypedArrayKind::Float64Array:
|
|
253
|
+
return get(runtime, Prop::Float64Array);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
jsi::PropNameID PropNameIDCache::createProp(jsi::Runtime &runtime, Prop prop) {
|
|
258
|
+
auto create = [&](const std::string &propName) {
|
|
259
|
+
return jsi::PropNameID::forUtf8(runtime, propName);
|
|
260
|
+
};
|
|
261
|
+
switch (prop) {
|
|
262
|
+
case Prop::Buffer:
|
|
263
|
+
return create("buffer");
|
|
264
|
+
case Prop::Constructor:
|
|
265
|
+
return create("constructor");
|
|
266
|
+
case Prop::Name:
|
|
267
|
+
return create("name");
|
|
268
|
+
case Prop::Proto:
|
|
269
|
+
return create("__proto__");
|
|
270
|
+
case Prop::Length:
|
|
271
|
+
return create("length");
|
|
272
|
+
case Prop::ByteLength:
|
|
273
|
+
return create("byteLength");
|
|
274
|
+
case Prop::ByteOffset:
|
|
275
|
+
return create("byteOffset");
|
|
276
|
+
case Prop::IsView:
|
|
277
|
+
return create("isView");
|
|
278
|
+
case Prop::ArrayBuffer:
|
|
279
|
+
return create("ArrayBuffer");
|
|
280
|
+
case Prop::Int8Array:
|
|
281
|
+
return create("Int8Array");
|
|
282
|
+
case Prop::Int16Array:
|
|
283
|
+
return create("Int16Array");
|
|
284
|
+
case Prop::Int32Array:
|
|
285
|
+
return create("Int32Array");
|
|
286
|
+
case Prop::Uint8Array:
|
|
287
|
+
return create("Uint8Array");
|
|
288
|
+
case Prop::Uint8ClampedArray:
|
|
289
|
+
return create("Uint8ClampedArray");
|
|
290
|
+
case Prop::Uint16Array:
|
|
291
|
+
return create("Uint16Array");
|
|
292
|
+
case Prop::Uint32Array:
|
|
293
|
+
return create("Uint32Array");
|
|
294
|
+
case Prop::Float32Array:
|
|
295
|
+
return create("Float32Array");
|
|
296
|
+
case Prop::Float64Array:
|
|
297
|
+
return create("Float64Array");
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
std::unordered_map<std::string, MGLTypedArrayKind> nameToKindMap = {
|
|
302
|
+
{"Int8Array", MGLTypedArrayKind::Int8Array},
|
|
303
|
+
{"Int16Array", MGLTypedArrayKind::Int16Array},
|
|
304
|
+
{"Int32Array", MGLTypedArrayKind::Int32Array},
|
|
305
|
+
{"Uint8Array", MGLTypedArrayKind::Uint8Array},
|
|
306
|
+
{"Uint8ClampedArray", MGLTypedArrayKind::Uint8ClampedArray},
|
|
307
|
+
{"Uint16Array", MGLTypedArrayKind::Uint16Array},
|
|
308
|
+
{"Uint32Array", MGLTypedArrayKind::Uint32Array},
|
|
309
|
+
{"Float32Array", MGLTypedArrayKind::Float32Array},
|
|
310
|
+
{"Float64Array", MGLTypedArrayKind::Float64Array},
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
MGLTypedArrayKind getTypedArrayKindForName(const std::string &name) {
|
|
314
|
+
return nameToKindMap.at(name);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
template class MGLTypedArray<MGLTypedArrayKind::Int8Array>;
|
|
318
|
+
template class MGLTypedArray<MGLTypedArrayKind::Int16Array>;
|
|
319
|
+
template class MGLTypedArray<MGLTypedArrayKind::Int32Array>;
|
|
320
|
+
template class MGLTypedArray<MGLTypedArrayKind::Uint8Array>;
|
|
321
|
+
template class MGLTypedArray<MGLTypedArrayKind::Uint8ClampedArray>;
|
|
322
|
+
template class MGLTypedArray<MGLTypedArrayKind::Uint16Array>;
|
|
323
|
+
template class MGLTypedArray<MGLTypedArrayKind::Uint32Array>;
|
|
324
|
+
template class MGLTypedArray<MGLTypedArrayKind::Float32Array>;
|
|
325
|
+
template class MGLTypedArray<MGLTypedArrayKind::Float64Array>;
|