react-native-quick-crypto 1.0.0 → 1.0.2

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 (92) hide show
  1. package/QuickCrypto.podspec +19 -52
  2. package/android/CMakeLists.txt +4 -2
  3. package/android/build.gradle +1 -1
  4. package/cpp/cipher/HybridCipher.cpp +20 -3
  5. package/cpp/cipher/HybridRsaCipher.cpp +20 -1
  6. package/cpp/ed25519/HybridEdKeyPair.cpp +8 -2
  7. package/cpp/keys/HybridKeyObjectHandle.cpp +8 -0
  8. package/cpp/keys/KeyObjectData.hpp +1 -1
  9. package/cpp/mldsa/HybridMlDsaKeyPair.cpp +264 -0
  10. package/cpp/mldsa/HybridMlDsaKeyPair.hpp +47 -0
  11. package/cpp/sign/HybridSignHandle.cpp +97 -22
  12. package/cpp/sign/HybridVerifyHandle.cpp +90 -21
  13. package/deps/ncrypto/.bazelignore +4 -0
  14. package/deps/ncrypto/.bazelrc +2 -0
  15. package/deps/ncrypto/.bazelversion +1 -0
  16. package/deps/ncrypto/.clang-format +111 -0
  17. package/deps/ncrypto/.github/workflows/bazel.yml +58 -0
  18. package/deps/ncrypto/.github/workflows/linter.yml +38 -0
  19. package/deps/ncrypto/.github/workflows/macos.yml +43 -0
  20. package/deps/ncrypto/.github/workflows/ubuntu.yml +46 -0
  21. package/deps/ncrypto/.github/workflows/visual-studio.yml +49 -0
  22. package/deps/ncrypto/.python-version +1 -0
  23. package/deps/ncrypto/BUILD.bazel +36 -0
  24. package/deps/ncrypto/CMakeLists.txt +55 -0
  25. package/deps/ncrypto/LICENSE +21 -0
  26. package/deps/ncrypto/MODULE.bazel +1 -0
  27. package/deps/ncrypto/MODULE.bazel.lock +280 -0
  28. package/deps/ncrypto/README.md +18 -0
  29. package/deps/ncrypto/WORKSPACE +15 -0
  30. package/deps/ncrypto/cmake/CPM.cmake +1225 -0
  31. package/deps/ncrypto/cmake/ncrypto-flags.cmake +16 -0
  32. package/deps/ncrypto/include/dh-primes.h +67 -0
  33. package/deps/ncrypto/{ncrypto.h → include/ncrypto.h} +361 -89
  34. package/deps/ncrypto/patches/0001-Expose-libdecrepit-so-NodeJS-can-use-it-for-ncrypto.patch +28 -0
  35. package/deps/ncrypto/pyproject.toml +38 -0
  36. package/deps/ncrypto/src/CMakeLists.txt +15 -0
  37. package/deps/ncrypto/src/engine.cpp +93 -0
  38. package/deps/ncrypto/{ncrypto.cc → src/ncrypto.cpp} +1168 -234
  39. package/deps/ncrypto/tests/BUILD.bazel +9 -0
  40. package/deps/ncrypto/tests/CMakeLists.txt +7 -0
  41. package/deps/ncrypto/tests/basic.cpp +86 -0
  42. package/deps/ncrypto/tools/run-clang-format.sh +42 -0
  43. package/lib/commonjs/ed.js +68 -0
  44. package/lib/commonjs/ed.js.map +1 -1
  45. package/lib/commonjs/keys/classes.js +6 -0
  46. package/lib/commonjs/keys/classes.js.map +1 -1
  47. package/lib/commonjs/mldsa.js +69 -0
  48. package/lib/commonjs/mldsa.js.map +1 -0
  49. package/lib/commonjs/specs/mlDsaKeyPair.nitro.js +6 -0
  50. package/lib/commonjs/specs/mlDsaKeyPair.nitro.js.map +1 -0
  51. package/lib/commonjs/subtle.js +483 -13
  52. package/lib/commonjs/subtle.js.map +1 -1
  53. package/lib/commonjs/utils/types.js.map +1 -1
  54. package/lib/module/ed.js +66 -0
  55. package/lib/module/ed.js.map +1 -1
  56. package/lib/module/keys/classes.js +6 -0
  57. package/lib/module/keys/classes.js.map +1 -1
  58. package/lib/module/mldsa.js +63 -0
  59. package/lib/module/mldsa.js.map +1 -0
  60. package/lib/module/specs/mlDsaKeyPair.nitro.js +4 -0
  61. package/lib/module/specs/mlDsaKeyPair.nitro.js.map +1 -0
  62. package/lib/module/subtle.js +484 -14
  63. package/lib/module/subtle.js.map +1 -1
  64. package/lib/module/utils/types.js.map +1 -1
  65. package/lib/tsconfig.tsbuildinfo +1 -1
  66. package/lib/typescript/ed.d.ts +4 -1
  67. package/lib/typescript/ed.d.ts.map +1 -1
  68. package/lib/typescript/index.d.ts +2 -0
  69. package/lib/typescript/index.d.ts.map +1 -1
  70. package/lib/typescript/keys/classes.d.ts +2 -0
  71. package/lib/typescript/keys/classes.d.ts.map +1 -1
  72. package/lib/typescript/mldsa.d.ts +18 -0
  73. package/lib/typescript/mldsa.d.ts.map +1 -0
  74. package/lib/typescript/specs/mlDsaKeyPair.nitro.d.ts +16 -0
  75. package/lib/typescript/specs/mlDsaKeyPair.nitro.d.ts.map +1 -0
  76. package/lib/typescript/subtle.d.ts +4 -1
  77. package/lib/typescript/subtle.d.ts.map +1 -1
  78. package/lib/typescript/utils/types.d.ts +14 -6
  79. package/lib/typescript/utils/types.d.ts.map +1 -1
  80. package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +1 -0
  81. package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +10 -0
  82. package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +10 -0
  83. package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +12 -0
  84. package/nitrogen/generated/shared/c++/HybridMlDsaKeyPairSpec.cpp +29 -0
  85. package/nitrogen/generated/shared/c++/HybridMlDsaKeyPairSpec.hpp +73 -0
  86. package/package.json +7 -3
  87. package/src/ed.ts +102 -0
  88. package/src/keys/classes.ts +9 -0
  89. package/src/mldsa.ts +125 -0
  90. package/src/specs/mlDsaKeyPair.nitro.ts +29 -0
  91. package/src/subtle.ts +667 -17
  92. package/src/utils/types.ts +27 -6
@@ -9,6 +9,12 @@
9
9
  #include <openssl/evp.h>
10
10
  #include <openssl/rsa.h>
11
11
 
12
+ #if OPENSSL_VERSION_NUMBER >= 0x30500000L
13
+ #define RNQC_HAS_ML_DSA 1
14
+ #else
15
+ #define RNQC_HAS_ML_DSA 0
16
+ #endif
17
+
12
18
  namespace margelo::nitro::crypto {
13
19
 
14
20
  using margelo::nitro::NativeArrayBuffer;
@@ -22,17 +28,28 @@ HybridSignHandle::~HybridSignHandle() {
22
28
 
23
29
  void HybridSignHandle::init(const std::string& algorithm) {
24
30
  algorithm_name = algorithm;
25
- md = getDigestByName(algorithm);
26
31
 
27
- md_ctx = EVP_MD_CTX_new();
28
- if (!md_ctx) {
29
- throw std::runtime_error("Failed to create message digest context");
30
- }
32
+ // For ML-DSA and other pure signature schemes, algorithm may be empty/null
33
+ if (!algorithm.empty()) {
34
+ md = getDigestByName(algorithm);
31
35
 
32
- if (EVP_DigestInit_ex(md_ctx, md, nullptr) <= 0) {
33
- EVP_MD_CTX_free(md_ctx);
34
- md_ctx = nullptr;
35
- throw std::runtime_error("Failed to initialize message digest");
36
+ md_ctx = EVP_MD_CTX_new();
37
+ if (!md_ctx) {
38
+ throw std::runtime_error("Failed to create message digest context");
39
+ }
40
+
41
+ if (EVP_DigestInit_ex(md_ctx, md, nullptr) <= 0) {
42
+ EVP_MD_CTX_free(md_ctx);
43
+ md_ctx = nullptr;
44
+ throw std::runtime_error("Failed to initialize message digest");
45
+ }
46
+ } else {
47
+ // No digest for pure signature schemes like ML-DSA
48
+ md = nullptr;
49
+ md_ctx = EVP_MD_CTX_new();
50
+ if (!md_ctx) {
51
+ throw std::runtime_error("Failed to create message digest context");
52
+ }
36
53
  }
37
54
  }
38
55
 
@@ -43,22 +60,60 @@ void HybridSignHandle::update(const std::shared_ptr<ArrayBuffer>& data) {
43
60
 
44
61
  auto native_data = ToNativeArrayBuffer(data);
45
62
 
46
- // Accumulate raw data for potential one-shot signing (Ed25519/Ed448)
63
+ // Accumulate raw data for potential one-shot signing (Ed25519/Ed448/ML-DSA)
47
64
  const uint8_t* ptr = reinterpret_cast<const uint8_t*>(native_data->data());
48
65
  data_buffer.insert(data_buffer.end(), ptr, ptr + native_data->size());
49
66
 
50
- if (EVP_DigestUpdate(md_ctx, native_data->data(), native_data->size()) <= 0) {
51
- unsigned long err = ERR_get_error();
52
- char err_buf[256];
53
- ERR_error_string_n(err, err_buf, sizeof(err_buf));
54
- throw std::runtime_error("Failed to update digest: " + std::string(err_buf));
67
+ // Only update digest if we have one (not needed for pure signature schemes)
68
+ if (md != nullptr) {
69
+ if (EVP_DigestUpdate(md_ctx, native_data->data(), native_data->size()) <= 0) {
70
+ unsigned long err = ERR_get_error();
71
+ char err_buf[256];
72
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
73
+ throw std::runtime_error("Failed to update digest: " + std::string(err_buf));
74
+ }
55
75
  }
56
76
  }
57
77
 
58
- // Check if key type requires one-shot signing (Ed25519, Ed448)
78
+ // Check if key type requires one-shot signing (Ed25519, Ed448, ML-DSA)
59
79
  static bool isOneShotVariant(EVP_PKEY* pkey) {
60
80
  int type = EVP_PKEY_id(pkey);
81
+ #if RNQC_HAS_ML_DSA
82
+ return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448 || type == EVP_PKEY_ML_DSA_44 || type == EVP_PKEY_ML_DSA_65 ||
83
+ type == EVP_PKEY_ML_DSA_87;
84
+ #else
61
85
  return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448;
86
+ #endif
87
+ }
88
+
89
+ // Get the algorithm name for creating PKEY_CTX (for ML-DSA variants)
90
+ static const char* getAlgorithmName(EVP_PKEY* pkey) {
91
+ int type = EVP_PKEY_id(pkey);
92
+ #if RNQC_HAS_ML_DSA
93
+ switch (type) {
94
+ case EVP_PKEY_ML_DSA_44:
95
+ return "ML-DSA-44";
96
+ case EVP_PKEY_ML_DSA_65:
97
+ return "ML-DSA-65";
98
+ case EVP_PKEY_ML_DSA_87:
99
+ return "ML-DSA-87";
100
+ case EVP_PKEY_ED25519:
101
+ return "ED25519";
102
+ case EVP_PKEY_ED448:
103
+ return "ED448";
104
+ default:
105
+ return nullptr;
106
+ }
107
+ #else
108
+ switch (type) {
109
+ case EVP_PKEY_ED25519:
110
+ return "ED25519";
111
+ case EVP_PKEY_ED448:
112
+ return "ED448";
113
+ default:
114
+ return nullptr;
115
+ }
116
+ #endif
62
117
  }
63
118
 
64
119
  std::shared_ptr<ArrayBuffer> HybridSignHandle::sign(const std::shared_ptr<HybridKeyObjectHandleSpec>& keyHandle,
@@ -78,18 +133,35 @@ std::shared_ptr<ArrayBuffer> HybridSignHandle::sign(const std::shared_ptr<Hybrid
78
133
  size_t sig_len = 0;
79
134
  std::unique_ptr<uint8_t[]> sig_buf;
80
135
 
81
- // Ed25519/Ed448 require one-shot signing with EVP_DigestSign
82
- if (isOneShotVariant(pkey)) {
136
+ int pkey_type = EVP_PKEY_id(pkey);
137
+ bool is_one_shot = isOneShotVariant(pkey);
138
+
139
+ // Ed25519/Ed448/ML-DSA require one-shot signing with EVP_DigestSign
140
+ // Also use one-shot path if no digest was specified (md == nullptr)
141
+ if (is_one_shot || md == nullptr) {
83
142
  // Create a new context for one-shot signing
84
143
  EVP_MD_CTX* sign_ctx = EVP_MD_CTX_new();
85
144
  if (!sign_ctx) {
86
145
  throw std::runtime_error("Failed to create signing context");
87
146
  }
88
147
 
89
- // Initialize for one-shot signing (pass nullptr for md - Ed25519/Ed448 have built-in hash)
90
- if (EVP_DigestSignInit(sign_ctx, nullptr, nullptr, nullptr, pkey) <= 0) {
148
+ // Get algorithm name and create PKEY_CTX for ML-DSA
149
+ const char* alg_name = getAlgorithmName(pkey);
150
+ EVP_PKEY_CTX* pkey_ctx = nullptr;
151
+ if (alg_name != nullptr) {
152
+ pkey_ctx = EVP_PKEY_CTX_new_from_name(nullptr, alg_name, nullptr);
153
+ if (!pkey_ctx) {
154
+ EVP_MD_CTX_free(sign_ctx);
155
+ throw std::runtime_error(std::string("Failed to create signing context for ") + alg_name);
156
+ }
157
+ }
158
+
159
+ // Initialize for one-shot signing (pass nullptr for md - these algorithms have built-in hash)
160
+ if (EVP_DigestSignInit(sign_ctx, pkey_ctx ? &pkey_ctx : nullptr, nullptr, nullptr, pkey) <= 0) {
91
161
  EVP_MD_CTX_free(sign_ctx);
92
- throw std::runtime_error("Failed to initialize Ed signing");
162
+ if (pkey_ctx)
163
+ EVP_PKEY_CTX_free(pkey_ctx);
164
+ throw std::runtime_error("Failed to initialize one-shot signing");
93
165
  }
94
166
 
95
167
  // Get the accumulated data from the digest context
@@ -130,7 +202,10 @@ std::shared_ptr<ArrayBuffer> HybridSignHandle::sign(const std::shared_ptr<Hybrid
130
202
 
131
203
  if (EVP_PKEY_sign_init(pkey_ctx) <= 0) {
132
204
  EVP_PKEY_CTX_free(pkey_ctx);
133
- throw std::runtime_error("Failed to initialize signing");
205
+ char err_buf[512];
206
+ snprintf(err_buf, sizeof(err_buf), "Failed to initialize signing for key type %d (expected one-shot: %s, RNQC_HAS_ML_DSA=%d)",
207
+ pkey_type, is_one_shot ? "true" : "false", RNQC_HAS_ML_DSA);
208
+ throw std::runtime_error(std::string(err_buf) + ": " + getOpenSSLError());
134
209
  }
135
210
 
136
211
  if (padding.has_value()) {
@@ -9,6 +9,12 @@
9
9
  #include <openssl/evp.h>
10
10
  #include <openssl/rsa.h>
11
11
 
12
+ #if OPENSSL_VERSION_NUMBER >= 0x30500000L
13
+ #define RNQC_HAS_ML_DSA 1
14
+ #else
15
+ #define RNQC_HAS_ML_DSA 0
16
+ #endif
17
+
12
18
  namespace margelo::nitro::crypto {
13
19
 
14
20
  using margelo::nitro::NativeArrayBuffer;
@@ -22,17 +28,28 @@ HybridVerifyHandle::~HybridVerifyHandle() {
22
28
 
23
29
  void HybridVerifyHandle::init(const std::string& algorithm) {
24
30
  algorithm_name = algorithm;
25
- md = getDigestByName(algorithm);
26
31
 
27
- md_ctx = EVP_MD_CTX_new();
28
- if (!md_ctx) {
29
- throw std::runtime_error("Failed to create message digest context");
30
- }
32
+ // For ML-DSA and other pure signature schemes, algorithm may be empty/null
33
+ if (!algorithm.empty()) {
34
+ md = getDigestByName(algorithm);
31
35
 
32
- if (EVP_DigestInit_ex(md_ctx, md, nullptr) <= 0) {
33
- EVP_MD_CTX_free(md_ctx);
34
- md_ctx = nullptr;
35
- throw std::runtime_error("Failed to initialize message digest");
36
+ md_ctx = EVP_MD_CTX_new();
37
+ if (!md_ctx) {
38
+ throw std::runtime_error("Failed to create message digest context");
39
+ }
40
+
41
+ if (EVP_DigestInit_ex(md_ctx, md, nullptr) <= 0) {
42
+ EVP_MD_CTX_free(md_ctx);
43
+ md_ctx = nullptr;
44
+ throw std::runtime_error("Failed to initialize message digest");
45
+ }
46
+ } else {
47
+ // No digest for pure signature schemes like ML-DSA
48
+ md = nullptr;
49
+ md_ctx = EVP_MD_CTX_new();
50
+ if (!md_ctx) {
51
+ throw std::runtime_error("Failed to create message digest context");
52
+ }
36
53
  }
37
54
  }
38
55
 
@@ -43,22 +60,60 @@ void HybridVerifyHandle::update(const std::shared_ptr<ArrayBuffer>& data) {
43
60
 
44
61
  auto native_data = ToNativeArrayBuffer(data);
45
62
 
46
- // Accumulate raw data for potential one-shot verification (Ed25519/Ed448)
63
+ // Accumulate raw data for potential one-shot verification (Ed25519/Ed448/ML-DSA)
47
64
  const uint8_t* ptr = reinterpret_cast<const uint8_t*>(native_data->data());
48
65
  data_buffer.insert(data_buffer.end(), ptr, ptr + native_data->size());
49
66
 
50
- if (EVP_DigestUpdate(md_ctx, native_data->data(), native_data->size()) <= 0) {
51
- unsigned long err = ERR_get_error();
52
- char err_buf[256];
53
- ERR_error_string_n(err, err_buf, sizeof(err_buf));
54
- throw std::runtime_error("Failed to update digest: " + std::string(err_buf));
67
+ // Only update digest if we have one (not needed for pure signature schemes)
68
+ if (md != nullptr) {
69
+ if (EVP_DigestUpdate(md_ctx, native_data->data(), native_data->size()) <= 0) {
70
+ unsigned long err = ERR_get_error();
71
+ char err_buf[256];
72
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
73
+ throw std::runtime_error("Failed to update digest: " + std::string(err_buf));
74
+ }
55
75
  }
56
76
  }
57
77
 
58
- // Check if key type requires one-shot verification (Ed25519, Ed448)
78
+ // Check if key type requires one-shot verification (Ed25519, Ed448, ML-DSA)
59
79
  static bool isOneShotVariant(EVP_PKEY* pkey) {
60
80
  int type = EVP_PKEY_id(pkey);
81
+ #if RNQC_HAS_ML_DSA
82
+ return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448 || type == EVP_PKEY_ML_DSA_44 || type == EVP_PKEY_ML_DSA_65 ||
83
+ type == EVP_PKEY_ML_DSA_87;
84
+ #else
61
85
  return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448;
86
+ #endif
87
+ }
88
+
89
+ // Get the algorithm name for creating PKEY_CTX (for ML-DSA variants)
90
+ static const char* getAlgorithmName(EVP_PKEY* pkey) {
91
+ int type = EVP_PKEY_id(pkey);
92
+ #if RNQC_HAS_ML_DSA
93
+ switch (type) {
94
+ case EVP_PKEY_ML_DSA_44:
95
+ return "ML-DSA-44";
96
+ case EVP_PKEY_ML_DSA_65:
97
+ return "ML-DSA-65";
98
+ case EVP_PKEY_ML_DSA_87:
99
+ return "ML-DSA-87";
100
+ case EVP_PKEY_ED25519:
101
+ return "ED25519";
102
+ case EVP_PKEY_ED448:
103
+ return "ED448";
104
+ default:
105
+ return nullptr;
106
+ }
107
+ #else
108
+ switch (type) {
109
+ case EVP_PKEY_ED25519:
110
+ return "ED25519";
111
+ case EVP_PKEY_ED448:
112
+ return "ED448";
113
+ default:
114
+ return nullptr;
115
+ }
116
+ #endif
62
117
  }
63
118
 
64
119
  bool HybridVerifyHandle::verify(const std::shared_ptr<HybridKeyObjectHandleSpec>& keyHandle, const std::shared_ptr<ArrayBuffer>& signature,
@@ -78,17 +133,31 @@ bool HybridVerifyHandle::verify(const std::shared_ptr<HybridKeyObjectHandleSpec>
78
133
  const unsigned char* sig_data = native_sig->data();
79
134
  size_t sig_len = native_sig->size();
80
135
 
81
- // Ed25519/Ed448 require one-shot verification with EVP_DigestVerify
82
- if (isOneShotVariant(pkey)) {
136
+ // Ed25519/Ed448/ML-DSA require one-shot verification with EVP_DigestVerify
137
+ // Also use one-shot path if no digest was specified (md == nullptr)
138
+ if (isOneShotVariant(pkey) || md == nullptr) {
83
139
  EVP_MD_CTX* verify_ctx = EVP_MD_CTX_new();
84
140
  if (!verify_ctx) {
85
141
  throw std::runtime_error("Failed to create verification context");
86
142
  }
87
143
 
88
- // Initialize for one-shot verification (pass nullptr for md - Ed25519/Ed448 have built-in hash)
89
- if (EVP_DigestVerifyInit(verify_ctx, nullptr, nullptr, nullptr, pkey) <= 0) {
144
+ // Get algorithm name and create PKEY_CTX for ML-DSA
145
+ const char* alg_name = getAlgorithmName(pkey);
146
+ EVP_PKEY_CTX* pkey_ctx = nullptr;
147
+ if (alg_name != nullptr) {
148
+ pkey_ctx = EVP_PKEY_CTX_new_from_name(nullptr, alg_name, nullptr);
149
+ if (!pkey_ctx) {
150
+ EVP_MD_CTX_free(verify_ctx);
151
+ throw std::runtime_error(std::string("Failed to create verification context for ") + alg_name);
152
+ }
153
+ }
154
+
155
+ // Initialize for one-shot verification (pass nullptr for md - these algorithms have built-in hash)
156
+ if (EVP_DigestVerifyInit(verify_ctx, pkey_ctx ? &pkey_ctx : nullptr, nullptr, nullptr, pkey) <= 0) {
90
157
  EVP_MD_CTX_free(verify_ctx);
91
- throw std::runtime_error("Failed to initialize Ed verification");
158
+ if (pkey_ctx)
159
+ EVP_PKEY_CTX_free(pkey_ctx);
160
+ throw std::runtime_error("Failed to initialize one-shot verification");
92
161
  }
93
162
 
94
163
  int result = EVP_DigestVerify(verify_ctx, sig_data, sig_len, data_buffer.data(), data_buffer.size());
@@ -0,0 +1,4 @@
1
+ build
2
+ cmake-build-debug-coverage
3
+ cmake-build-debug
4
+ cmake-build-release
@@ -0,0 +1,2 @@
1
+ common --enable_workspace
2
+ build --cxxopt="-std=c++20"
@@ -0,0 +1 @@
1
+ 8.0.0
@@ -0,0 +1,111 @@
1
+ ---
2
+ Language: Cpp
3
+ # BasedOnStyle: Google
4
+ AccessModifierOffset: -1
5
+ AlignAfterOpenBracket: Align
6
+ AlignConsecutiveAssignments: false
7
+ AlignConsecutiveDeclarations: false
8
+ AlignEscapedNewlines: Right
9
+ AlignOperands: true
10
+ AlignTrailingComments: true
11
+ AllowAllParametersOfDeclarationOnNextLine: true
12
+ AllowShortBlocksOnASingleLine: false
13
+ AllowShortCaseLabelsOnASingleLine: false
14
+ AllowShortFunctionsOnASingleLine: Inline
15
+ AllowShortIfStatementsOnASingleLine: true
16
+ AllowShortLoopsOnASingleLine: true
17
+ AlwaysBreakAfterDefinitionReturnType: None
18
+ AlwaysBreakAfterReturnType: None
19
+ AlwaysBreakBeforeMultilineStrings: false
20
+ AlwaysBreakTemplateDeclarations: true
21
+ BinPackArguments: false
22
+ BinPackParameters: false
23
+ BraceWrapping:
24
+ AfterClass: false
25
+ AfterControlStatement: false
26
+ AfterEnum: false
27
+ AfterFunction: false
28
+ AfterNamespace: false
29
+ AfterObjCDeclaration: false
30
+ AfterStruct: false
31
+ AfterUnion: false
32
+ AfterExternBlock: false
33
+ BeforeCatch: false
34
+ BeforeElse: false
35
+ IndentBraces: false
36
+ SplitEmptyFunction: true
37
+ SplitEmptyRecord: true
38
+ SplitEmptyNamespace: true
39
+ BreakBeforeBinaryOperators: None
40
+ BreakBeforeBraces: Attach
41
+ BreakBeforeInheritanceComma: false
42
+ BreakBeforeTernaryOperators: true
43
+ BreakConstructorInitializersBeforeComma: false
44
+ BreakConstructorInitializers: BeforeColon
45
+ BreakAfterJavaFieldAnnotations: false
46
+ BreakStringLiterals: true
47
+ ColumnLimit: 80
48
+ CommentPragmas: '^ IWYU pragma:'
49
+ CompactNamespaces: false
50
+ ConstructorInitializerAllOnOneLineOrOnePerLine: true
51
+ ConstructorInitializerIndentWidth: 4
52
+ ContinuationIndentWidth: 4
53
+ Cpp11BracedListStyle: true
54
+ DerivePointerAlignment: false
55
+ DisableFormat: false
56
+ ExperimentalAutoDetectBinPacking: false
57
+ FixNamespaceComments: true
58
+ ForEachMacros:
59
+ - foreach
60
+ - Q_FOREACH
61
+ - BOOST_FOREACH
62
+ IncludeBlocks: Preserve
63
+ IncludeCategories:
64
+ - Regex: '^<ext/.*\.h>'
65
+ Priority: 2
66
+ - Regex: '^<.*\.h>'
67
+ Priority: 1
68
+ - Regex: '^<.*'
69
+ Priority: 2
70
+ - Regex: '.*'
71
+ Priority: 3
72
+ IncludeIsMainRegex: '([-_](test|unittest))?$'
73
+ IndentCaseLabels: true
74
+ IndentPPDirectives: None
75
+ IndentWidth: 2
76
+ IndentWrappedFunctionNames: false
77
+ JavaScriptQuotes: Leave
78
+ JavaScriptWrapImports: true
79
+ KeepEmptyLinesAtTheStartOfBlocks: false
80
+ MacroBlockBegin: ''
81
+ MacroBlockEnd: ''
82
+ MaxEmptyLinesToKeep: 1
83
+ NamespaceIndentation: None
84
+ ObjCBlockIndentWidth: 2
85
+ ObjCSpaceAfterProperty: false
86
+ ObjCSpaceBeforeProtocolList: false
87
+ PenaltyBreakAssignment: 2
88
+ PenaltyBreakBeforeFirstCallParameter: 1
89
+ PenaltyBreakComment: 300
90
+ PenaltyBreakFirstLessLess: 120
91
+ PenaltyBreakString: 1000
92
+ PenaltyExcessCharacter: 1000000
93
+ PenaltyReturnTypeOnItsOwnLine: 200
94
+ PointerAlignment: Left
95
+ ReflowComments: true
96
+ SortIncludes: true
97
+ SortUsingDeclarations: true
98
+ SpaceAfterCStyleCast: false
99
+ SpaceAfterTemplateKeyword: true
100
+ SpaceBeforeAssignmentOperators: true
101
+ SpaceBeforeParens: ControlStatements
102
+ SpaceInEmptyParentheses: false
103
+ SpacesBeforeTrailingComments: 2
104
+ SpacesInAngles: false
105
+ SpacesInContainerLiterals: true
106
+ SpacesInCStyleCastParentheses: false
107
+ SpacesInParentheses: false
108
+ SpacesInSquareBrackets: false
109
+ Standard: Auto
110
+ TabWidth: 8
111
+ UseTab: Never
@@ -0,0 +1,58 @@
1
+ name: Bazel
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, ready_for_review]
6
+ paths-ignore:
7
+ - '**.md'
8
+ - 'docs/**'
9
+ push:
10
+ branches:
11
+ - main
12
+ paths-ignore:
13
+ - '**.md'
14
+ - 'docs/**'
15
+
16
+ permissions:
17
+ contents: read
18
+ actions: write
19
+
20
+ concurrency:
21
+ group: ${{ github.workflow }}-${{ github.ref }}
22
+ cancel-in-progress: true
23
+
24
+ jobs:
25
+ macos:
26
+ runs-on: macos-latest
27
+ steps:
28
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
29
+ - uses: bazel-contrib/setup-bazel@bbf8fe8b219f642c7f8bc673215f28eb1d9dec51 # v0.10.0
30
+ with:
31
+ bazelisk-cache: true
32
+ disk-cache: ${{ github.workflow }}
33
+ repository-cache: true
34
+ - name: Build & Test
35
+ run: bazel test //...
36
+ ubuntu:
37
+ strategy:
38
+ fail-fast: false
39
+ matrix:
40
+ shared: [ON, OFF]
41
+ include:
42
+ - cc: gcc-14
43
+ cxx: g++-14
44
+ - cc: clang-18
45
+ cxx: clang++-18
46
+ runs-on: ubuntu-latest
47
+ steps:
48
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
49
+ - uses: bazel-contrib/setup-bazel@bbf8fe8b219f642c7f8bc673215f28eb1d9dec51 # v0.10.0
50
+ with:
51
+ bazelisk-cache: true
52
+ disk-cache: ${{ github.workflow }}
53
+ repository-cache: true
54
+ - name: Build & Test
55
+ run: bazel test //...
56
+ env:
57
+ CC: ${{matrix.cc}}
58
+ CXX: ${{matrix.cxx}}
@@ -0,0 +1,38 @@
1
+ name: Linter
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, ready_for_review]
6
+ paths-ignore:
7
+ - '**.md'
8
+ - 'docs/**'
9
+ push:
10
+ branches:
11
+ - main
12
+ paths-ignore:
13
+ - '**.md'
14
+ - 'docs/**'
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ concurrency:
20
+ group: ${{ github.workflow }}-${{ github.ref }}
21
+ cancel-in-progress: true
22
+
23
+ jobs:
24
+ lint:
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
28
+
29
+ - name: Run clang-format
30
+ uses: jidicula/clang-format-action@c74383674bf5f7c69f60ce562019c1c94bc1421a # v4.13.0
31
+ with:
32
+ clang-format-version: '17'
33
+ fallback-style: 'Google'
34
+
35
+ - uses: chartboost/ruff-action@e18ae971ccee1b2d7bbef113930f00c670b78da4 # v1.0.0
36
+ name: Lint with Ruff
37
+ with:
38
+ version: 0.5.1
@@ -0,0 +1,43 @@
1
+ name: macOS
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, ready_for_review]
6
+ paths-ignore:
7
+ - '**.md'
8
+ - 'docs/**'
9
+ push:
10
+ branches:
11
+ - main
12
+ paths-ignore:
13
+ - '**.md'
14
+ - 'docs/**'
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ concurrency:
20
+ group: ${{ github.workflow }}-${{ github.ref }}
21
+ cancel-in-progress: true
22
+
23
+ jobs:
24
+ ubuntu-build:
25
+ strategy:
26
+ fail-fast: false
27
+ matrix:
28
+ runs-on: [macos-14, macos-15]
29
+ runs-on: ${{matrix.runs-on}}
30
+ steps:
31
+ - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
32
+ - name: ccache
33
+ uses: hendrikmuhs/ccache-action@v1.2
34
+ with:
35
+ key: ${{github.job}}-${{matrix.os}}
36
+ - name: Prepare
37
+ run: cmake -B build
38
+ - name: Build
39
+ # m1 machines have 3 CPU
40
+ # Ref: https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners
41
+ run: cmake --build build -j=3
42
+ - name: Test
43
+ run: ctest --output-on-failure --test-dir build
@@ -0,0 +1,46 @@
1
+ name: Ubuntu
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, ready_for_review]
6
+ paths-ignore:
7
+ - '**.md'
8
+ - 'docs/**'
9
+ push:
10
+ branches:
11
+ - main
12
+ paths-ignore:
13
+ - '**.md'
14
+ - 'docs/**'
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ concurrency:
20
+ group: ${{ github.workflow }}-${{ github.ref }}
21
+ cancel-in-progress: true
22
+
23
+ jobs:
24
+ build:
25
+ strategy:
26
+ matrix:
27
+ runs-on: [ubuntu-latest]
28
+ shared: [ON, OFF]
29
+ cxx: [g++-14]
30
+ runs-on: ${{matrix.runs-on}}
31
+ steps:
32
+ - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
33
+ - name: ccache
34
+ uses: hendrikmuhs/ccache-action@v1.2
35
+ with:
36
+ key: ${{github.job}}-${{matrix.os}}-{{matrix.shared}}
37
+ - name: Setup Ninja
38
+ run: sudo apt-get install ninja-build
39
+ - name: Prepare
40
+ run: cmake -DBUILD_SHARED_LIBS=${{matrix.shared}} -G Ninja -B build
41
+ env:
42
+ CXX: ${{matrix.cxx}}
43
+ - name: Build
44
+ run: cmake --build build -j=4
45
+ - name: Test
46
+ run: ctest --output-on-failure --test-dir build
@@ -0,0 +1,49 @@
1
+ name: Windows
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, ready_for_review]
6
+ paths-ignore:
7
+ - '**.md'
8
+ - 'docs/**'
9
+ push:
10
+ branches:
11
+ - main
12
+ paths-ignore:
13
+ - '**.md'
14
+ - 'docs/**'
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ concurrency:
20
+ group: ${{ github.workflow }}-${{ github.ref }}
21
+ cancel-in-progress: true
22
+
23
+ jobs:
24
+ build:
25
+ runs-on: windows-2025
26
+ strategy:
27
+ fail-fast: false
28
+ matrix:
29
+ include:
30
+ - {gen: Visual Studio 17 2022, arch: x64, config: Release}
31
+ - {gen: Visual Studio 17 2022, arch: x64, config: Debug}
32
+ steps:
33
+ - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
34
+ - name: ccache
35
+ uses: hendrikmuhs/ccache-action@v1.2
36
+ with:
37
+ key: ${{github.job}}-${{matrix.os}}-${{matrix.config}}
38
+ - name: Install Dependencies
39
+ run: |
40
+ choco install nasm
41
+ echo "C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
42
+ - name: Configure
43
+ run: |
44
+ cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -B build
45
+ - name: Build
46
+ run: cmake --build build --config "${{matrix.config}}" --verbose
47
+ - name: Run tests
48
+ working-directory: build
49
+ run: ctest -C "${{matrix.config}}" --output-on-failure