@json-eval-rs/react-native 0.0.28

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.
@@ -0,0 +1,1366 @@
1
+ #include "json-eval-bridge.h"
2
+ #include <map>
3
+ #include <mutex>
4
+ #include <memory>
5
+
6
+ // Forward declarations for FFI functions
7
+ extern "C" {
8
+ typedef struct {
9
+ void* inner;
10
+ } JSONEvalHandle;
11
+
12
+ typedef struct {
13
+ bool success;
14
+ const uint8_t* data_ptr;
15
+ size_t data_len;
16
+ char* error;
17
+ void* _owned_data;
18
+ } FFIResult;
19
+
20
+ JSONEvalHandle* json_eval_new(const char* schema, const char* context, const char* data);
21
+ JSONEvalHandle* json_eval_new_from_msgpack(const uint8_t* schema_msgpack, size_t schema_len, const char* context, const char* data);
22
+ FFIResult json_eval_evaluate(JSONEvalHandle* handle, const char* data, const char* context);
23
+ FFIResult json_eval_get_evaluated_schema_msgpack(JSONEvalHandle* handle, bool skip_layout);
24
+ FFIResult json_eval_validate(JSONEvalHandle* handle, const char* data, const char* context);
25
+ FFIResult json_eval_evaluate_dependents(JSONEvalHandle* handle, const char* changed_path, const char* data, const char* context, int re_evaluate);
26
+ FFIResult json_eval_get_evaluated_schema(JSONEvalHandle* handle, bool skip_layout);
27
+ FFIResult json_eval_get_schema_value(JSONEvalHandle* handle);
28
+ FFIResult json_eval_get_evaluated_schema_without_params(JSONEvalHandle* handle, bool skip_layout);
29
+ FFIResult json_eval_get_evaluated_schema_by_path(JSONEvalHandle* handle, const char* path, bool skip_layout);
30
+ FFIResult json_eval_get_evaluated_schema_by_paths(JSONEvalHandle* handle, const char* paths_json, bool skip_layout);
31
+ FFIResult json_eval_get_schema_by_path(JSONEvalHandle* handle, const char* path);
32
+ FFIResult json_eval_get_schema_by_paths(JSONEvalHandle* handle, const char* paths_json);
33
+ FFIResult json_eval_resolve_layout(JSONEvalHandle* handle, bool evaluate);
34
+ FFIResult json_eval_compile_and_run_logic(JSONEvalHandle* handle, const char* logic_str, const char* data, const char* context);
35
+ uint64_t json_eval_compile_logic(JSONEvalHandle* handle, const char* logic_str);
36
+ FFIResult json_eval_run_logic(JSONEvalHandle* handle, uint64_t logic_id, const char* data, const char* context);
37
+ FFIResult json_eval_reload_schema(JSONEvalHandle* handle, const char* schema, const char* context, const char* data);
38
+ FFIResult json_eval_reload_schema_msgpack(JSONEvalHandle* handle, const uint8_t* schema_msgpack, size_t schema_len, const char* context, const char* data);
39
+ FFIResult json_eval_reload_schema_from_cache(JSONEvalHandle* handle, const char* cache_key, const char* context, const char* data);
40
+ JSONEvalHandle* json_eval_new_from_cache(const char* cache_key, const char* context, const char* data);
41
+ FFIResult json_eval_cache_stats(JSONEvalHandle* handle);
42
+ FFIResult json_eval_clear_cache(JSONEvalHandle* handle);
43
+ FFIResult json_eval_cache_len(JSONEvalHandle* handle);
44
+ FFIResult json_eval_enable_cache(JSONEvalHandle* handle);
45
+ FFIResult json_eval_disable_cache(JSONEvalHandle* handle);
46
+ int json_eval_is_cache_enabled(JSONEvalHandle* handle);
47
+ FFIResult json_eval_validate_paths(JSONEvalHandle* handle, const char* data, const char* context, const char* paths_json);
48
+
49
+ // Subform FFI methods
50
+ FFIResult json_eval_evaluate_subform(JSONEvalHandle* handle, const char* subform_path, const char* data, const char* context);
51
+ FFIResult json_eval_validate_subform(JSONEvalHandle* handle, const char* subform_path, const char* data, const char* context);
52
+ FFIResult json_eval_evaluate_dependents_subform(JSONEvalHandle* handle, const char* subform_path, const char* changed_path, const char* data, const char* context);
53
+ FFIResult json_eval_resolve_layout_subform(JSONEvalHandle* handle, const char* subform_path, bool evaluate);
54
+ FFIResult json_eval_get_evaluated_schema_subform(JSONEvalHandle* handle, const char* subform_path, bool resolve_layout);
55
+ FFIResult json_eval_get_schema_value_subform(JSONEvalHandle* handle, const char* subform_path);
56
+ FFIResult json_eval_get_evaluated_schema_without_params_subform(JSONEvalHandle* handle, const char* subform_path, bool resolve_layout);
57
+ FFIResult json_eval_get_evaluated_schema_by_path_subform(JSONEvalHandle* handle, const char* subform_path, const char* schema_path, bool skip_layout);
58
+ FFIResult json_eval_get_evaluated_schema_by_paths_subform(JSONEvalHandle* handle, const char* subform_path, const char* schema_paths_json, bool skip_layout);
59
+ FFIResult json_eval_get_schema_by_path_subform(JSONEvalHandle* handle, const char* subform_path, const char* schema_path);
60
+ FFIResult json_eval_get_schema_by_paths_subform(JSONEvalHandle* handle, const char* subform_path, const char* schema_paths_json);
61
+ FFIResult json_eval_get_subform_paths(JSONEvalHandle* handle);
62
+ FFIResult json_eval_has_subform(JSONEvalHandle* handle, const char* subform_path);
63
+
64
+ void json_eval_free(JSONEvalHandle* handle);
65
+ void json_eval_free_result(FFIResult result);
66
+ const char* json_eval_version();
67
+ void json_eval_free_string(char* ptr);
68
+ }
69
+
70
+ namespace jsoneval {
71
+
72
+ // Handle storage
73
+ static std::map<std::string, JSONEvalHandle*> handles;
74
+ static std::mutex handlesMutex;
75
+ static int handleCounter = 0;
76
+
77
+ std::string JsonEvalBridge::create(
78
+ const std::string& schema,
79
+ const std::string& context,
80
+ const std::string& data
81
+ ) {
82
+ const char* ctx = context.empty() ? nullptr : context.c_str();
83
+ const char* dt = data.empty() ? nullptr : data.c_str();
84
+
85
+ JSONEvalHandle* handle = json_eval_new(schema.c_str(), ctx, dt);
86
+
87
+ if (handle == nullptr) {
88
+ throw std::runtime_error("Failed to create JSONEval instance");
89
+ }
90
+
91
+ std::lock_guard<std::mutex> lock(handlesMutex);
92
+ std::string handleId = "handle_" + std::to_string(handleCounter++);
93
+ handles[handleId] = handle;
94
+
95
+ return handleId;
96
+ }
97
+
98
+ std::string JsonEvalBridge::createFromMsgpack(
99
+ const std::vector<uint8_t>& schemaMsgpack,
100
+ const std::string& context,
101
+ const std::string& data
102
+ ) {
103
+ const char* ctx = context.empty() ? nullptr : context.c_str();
104
+ const char* dt = data.empty() ? nullptr : data.c_str();
105
+
106
+ JSONEvalHandle* handle = json_eval_new_from_msgpack(
107
+ schemaMsgpack.data(),
108
+ schemaMsgpack.size(),
109
+ ctx,
110
+ dt
111
+ );
112
+
113
+ if (handle == nullptr) {
114
+ throw std::runtime_error("Failed to create JSONEval instance from MessagePack");
115
+ }
116
+
117
+ std::lock_guard<std::mutex> lock(handlesMutex);
118
+ std::string handleId = "handle_" + std::to_string(handleCounter++);
119
+ handles[handleId] = handle;
120
+
121
+ return handleId;
122
+ }
123
+
124
+ std::string JsonEvalBridge::createFromCache(
125
+ const std::string& cacheKey,
126
+ const std::string& context,
127
+ const std::string& data
128
+ ) {
129
+ const char* ctx = context.empty() ? nullptr : context.c_str();
130
+ const char* dt = data.empty() ? nullptr : data.c_str();
131
+
132
+ JSONEvalHandle* handle = json_eval_new_from_cache(
133
+ cacheKey.c_str(),
134
+ ctx,
135
+ dt
136
+ );
137
+
138
+ if (handle == nullptr) {
139
+ throw std::runtime_error("Failed to create JSONEval instance from cache");
140
+ }
141
+
142
+ std::lock_guard<std::mutex> lock(handlesMutex);
143
+ std::string handleId = "handle_" + std::to_string(handleCounter++);
144
+ handles[handleId] = handle;
145
+
146
+ return handleId;
147
+ }
148
+
149
+ template<typename Func>
150
+ void JsonEvalBridge::runAsync(Func&& func, std::function<void(const std::string&, const std::string&)> callback) {
151
+ std::thread([func = std::forward<Func>(func), callback]() {
152
+ try {
153
+ std::string result = func();
154
+ callback(result, "");
155
+ } catch (const std::exception& e) {
156
+ callback("", e.what());
157
+ }
158
+ }).detach();
159
+ }
160
+
161
+ void JsonEvalBridge::evaluateAsync(
162
+ const std::string& handleId,
163
+ const std::string& data,
164
+ const std::string& context,
165
+ std::function<void(const std::string&, const std::string&)> callback
166
+ ) {
167
+ runAsync([handleId, data, context]() -> std::string {
168
+ std::lock_guard<std::mutex> lock(handlesMutex);
169
+ auto it = handles.find(handleId);
170
+ if (it == handles.end()) {
171
+ throw std::runtime_error("Invalid handle");
172
+ }
173
+
174
+ // Step 1: Evaluate (no longer returns data)
175
+ const char* ctx = context.empty() ? nullptr : context.c_str();
176
+ FFIResult evalResult = json_eval_evaluate(it->second, data.c_str(), ctx);
177
+
178
+ if (!evalResult.success) {
179
+ std::string error = evalResult.error ? evalResult.error : "Unknown error";
180
+ json_eval_free_result(evalResult);
181
+ throw std::runtime_error(error);
182
+ }
183
+ json_eval_free_result(evalResult);
184
+
185
+ // Step 2: Get the evaluated schema
186
+ FFIResult schemaResult = json_eval_get_evaluated_schema(it->second, true);
187
+
188
+ if (!schemaResult.success) {
189
+ std::string error = schemaResult.error ? schemaResult.error : "Unknown error";
190
+ json_eval_free_result(schemaResult);
191
+ throw std::runtime_error(error);
192
+ }
193
+
194
+ // Zero-copy: construct string directly from raw pointer without intermediate copy
195
+ std::string resultStr;
196
+ if (schemaResult.data_ptr && schemaResult.data_len > 0) {
197
+ // Use string constructor that takes pointer + length (still copies, but single copy)
198
+ resultStr.assign(reinterpret_cast<const char*>(schemaResult.data_ptr), schemaResult.data_len);
199
+ } else {
200
+ resultStr = "{}";
201
+ }
202
+ json_eval_free_result(schemaResult);
203
+ return resultStr;
204
+ }, callback);
205
+ }
206
+
207
+ uint64_t JsonEvalBridge::compileLogic(
208
+ const std::string& handleId,
209
+ const std::string& logicStr
210
+ ) {
211
+ std::lock_guard<std::mutex> lock(handlesMutex);
212
+ auto it = handles.find(handleId);
213
+ if (it == handles.end()) {
214
+ throw std::runtime_error("Invalid handle");
215
+ }
216
+
217
+ uint64_t logicId = json_eval_compile_logic(it->second, logicStr.c_str());
218
+ if (logicId == 0) {
219
+ throw std::runtime_error("Failed to compile logic (received ID 0)");
220
+ }
221
+
222
+ return logicId;
223
+ }
224
+
225
+ void JsonEvalBridge::runLogicAsync(
226
+ const std::string& handleId,
227
+ uint64_t logicId,
228
+ const std::string& data,
229
+ const std::string& context,
230
+ std::function<void(const std::string&, const std::string&)> callback
231
+ ) {
232
+ runAsync([handleId, logicId, data, context]() -> std::string {
233
+ std::lock_guard<std::mutex> lock(handlesMutex);
234
+ auto it = handles.find(handleId);
235
+ if (it == handles.end()) {
236
+ throw std::runtime_error("Invalid handle");
237
+ }
238
+
239
+ FFIResult result = json_eval_run_logic(
240
+ it->second,
241
+ logicId,
242
+ data.empty() ? nullptr : data.c_str(),
243
+ context.empty() ? nullptr : context.c_str()
244
+ );
245
+
246
+ if (!result.success) {
247
+ std::string error = result.error ? result.error : "Unknown error";
248
+ json_eval_free_result(result);
249
+ throw std::runtime_error(error);
250
+ }
251
+
252
+ std::string resultStr;
253
+ if (result.data_ptr && result.data_len > 0) {
254
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
255
+ } else {
256
+ resultStr = "{}";
257
+ }
258
+ json_eval_free_result(result);
259
+ return resultStr;
260
+ }, callback);
261
+ }
262
+
263
+ void JsonEvalBridge::validateAsync(
264
+ const std::string& handleId,
265
+ const std::string& data,
266
+ const std::string& context,
267
+ std::function<void(const std::string&, const std::string&)> callback
268
+ ) {
269
+ runAsync([handleId, data, context]() -> std::string {
270
+ std::lock_guard<std::mutex> lock(handlesMutex);
271
+ auto it = handles.find(handleId);
272
+ if (it == handles.end()) {
273
+ throw std::runtime_error("Invalid handle");
274
+ }
275
+
276
+ const char* ctx = context.empty() ? nullptr : context.c_str();
277
+ FFIResult result = json_eval_validate(it->second, data.c_str(), ctx);
278
+
279
+ if (!result.success) {
280
+ std::string error = result.error ? result.error : "Unknown error";
281
+ json_eval_free_result(result);
282
+ throw std::runtime_error(error);
283
+ }
284
+
285
+ // Zero-copy: construct string directly from raw pointer
286
+ std::string resultStr;
287
+ if (result.data_ptr && result.data_len > 0) {
288
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
289
+ } else {
290
+ resultStr = "{}";
291
+ }
292
+ json_eval_free_result(result);
293
+ return resultStr;
294
+ }, callback);
295
+ }
296
+
297
+ void JsonEvalBridge::evaluateDependentsAsync(
298
+ const std::string& handleId,
299
+ const std::string& changedPathsJson,
300
+ const std::string& data,
301
+ const std::string& context,
302
+ bool reEvaluate,
303
+ std::function<void(const std::string&, const std::string&)> callback
304
+ ) {
305
+ runAsync([handleId, changedPathsJson, data, context, reEvaluate]() -> std::string {
306
+ std::lock_guard<std::mutex> lock(handlesMutex);
307
+ auto it = handles.find(handleId);
308
+ if (it == handles.end()) {
309
+ throw std::runtime_error("Invalid handle");
310
+ }
311
+
312
+ const char* dataPtr = data.empty() ? nullptr : data.c_str();
313
+ const char* ctx = context.empty() ? nullptr : context.c_str();
314
+ FFIResult result = json_eval_evaluate_dependents(
315
+ it->second,
316
+ changedPathsJson.c_str(),
317
+ dataPtr,
318
+ ctx,
319
+ reEvaluate ? 1 : 0
320
+ );
321
+
322
+ if (!result.success) {
323
+ std::string error = result.error ? result.error : "Unknown error";
324
+ json_eval_free_result(result);
325
+ throw std::runtime_error(error);
326
+ }
327
+
328
+ // Zero-copy: construct string directly from raw pointer
329
+ std::string resultStr;
330
+ if (result.data_ptr && result.data_len > 0) {
331
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
332
+ } else {
333
+ resultStr = "{}";
334
+ }
335
+ json_eval_free_result(result);
336
+ return resultStr;
337
+ }, callback);
338
+ }
339
+
340
+ void JsonEvalBridge::getEvaluatedSchemaAsync(
341
+ const std::string& handleId,
342
+ bool skipLayout,
343
+ std::function<void(const std::string&, const std::string&)> callback
344
+ ) {
345
+ runAsync([handleId, skipLayout]() -> std::string {
346
+ std::lock_guard<std::mutex> lock(handlesMutex);
347
+ auto it = handles.find(handleId);
348
+ if (it == handles.end()) {
349
+ throw std::runtime_error("Invalid handle");
350
+ }
351
+
352
+ FFIResult result = json_eval_get_evaluated_schema(it->second, skipLayout);
353
+
354
+ if (!result.success) {
355
+ std::string error = result.error ? result.error : "Unknown error";
356
+ json_eval_free_result(result);
357
+ throw std::runtime_error(error);
358
+ }
359
+
360
+ // Zero-copy: construct string directly from raw pointer
361
+ std::string resultStr;
362
+ if (result.data_ptr && result.data_len > 0) {
363
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
364
+ } else {
365
+ resultStr = "{}";
366
+ }
367
+ json_eval_free_result(result);
368
+ return resultStr;
369
+ }, callback);
370
+ }
371
+
372
+ void JsonEvalBridge::getEvaluatedSchemaMsgpackAsync(
373
+ const std::string& handleId,
374
+ bool skipLayout,
375
+ std::function<void(const std::string&, const std::string&)> callback
376
+ ) {
377
+ runAsync([handleId, skipLayout]() -> std::string {
378
+ std::lock_guard<std::mutex> lock(handlesMutex);
379
+ auto it = handles.find(handleId);
380
+ if (it == handles.end()) {
381
+ throw std::runtime_error("Invalid handle");
382
+ }
383
+
384
+ FFIResult result = json_eval_get_evaluated_schema_msgpack(it->second, skipLayout);
385
+
386
+ if (!result.success) {
387
+ std::string error = result.error ? result.error : "Unknown error";
388
+ json_eval_free_result(result);
389
+ throw std::runtime_error(error);
390
+ }
391
+
392
+ // Zero-copy: construct string directly from raw pointer (binary data)
393
+ std::string resultStr;
394
+ if (result.data_ptr && result.data_len > 0) {
395
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
396
+ } else {
397
+ resultStr = "";
398
+ }
399
+ json_eval_free_result(result);
400
+ return resultStr;
401
+ }, callback);
402
+ }
403
+
404
+ void JsonEvalBridge::getSchemaValueAsync(
405
+ const std::string& handleId,
406
+ std::function<void(const std::string&, const std::string&)> callback
407
+ ) {
408
+ runAsync([handleId]() -> std::string {
409
+ std::lock_guard<std::mutex> lock(handlesMutex);
410
+ auto it = handles.find(handleId);
411
+ if (it == handles.end()) {
412
+ throw std::runtime_error("Invalid handle");
413
+ }
414
+
415
+ FFIResult result = json_eval_get_schema_value(it->second);
416
+
417
+ if (!result.success) {
418
+ std::string error = result.error ? result.error : "Unknown error";
419
+ json_eval_free_result(result);
420
+ throw std::runtime_error(error);
421
+ }
422
+
423
+ // Zero-copy: construct string directly from raw pointer
424
+ std::string resultStr;
425
+ if (result.data_ptr && result.data_len > 0) {
426
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
427
+ } else {
428
+ resultStr = "{}";
429
+ }
430
+ json_eval_free_result(result);
431
+ return resultStr;
432
+ }, callback);
433
+ }
434
+
435
+ void JsonEvalBridge::getEvaluatedSchemaWithoutParamsAsync(
436
+ const std::string& handleId,
437
+ bool skipLayout,
438
+ std::function<void(const std::string&, const std::string&)> callback
439
+ ) {
440
+ runAsync([handleId, skipLayout]() -> std::string {
441
+ std::lock_guard<std::mutex> lock(handlesMutex);
442
+ auto it = handles.find(handleId);
443
+ if (it == handles.end()) {
444
+ throw std::runtime_error("Invalid handle");
445
+ }
446
+
447
+ FFIResult result = json_eval_get_evaluated_schema_without_params(it->second, skipLayout);
448
+
449
+ if (!result.success) {
450
+ std::string error = result.error ? result.error : "Unknown error";
451
+ json_eval_free_result(result);
452
+ throw std::runtime_error(error);
453
+ }
454
+
455
+ // Zero-copy: construct string directly from raw pointer
456
+ std::string resultStr;
457
+ if (result.data_ptr && result.data_len > 0) {
458
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
459
+ } else {
460
+ resultStr = "{}";
461
+ }
462
+ json_eval_free_result(result);
463
+ return resultStr;
464
+ }, callback);
465
+ }
466
+
467
+ void JsonEvalBridge::getEvaluatedSchemaByPathAsync(
468
+ const std::string& handleId,
469
+ const std::string& path,
470
+ bool skipLayout,
471
+ std::function<void(const std::string&, const std::string&)> callback
472
+ ) {
473
+ runAsync([handleId, path, skipLayout]() -> std::string {
474
+ std::lock_guard<std::mutex> lock(handlesMutex);
475
+ auto it = handles.find(handleId);
476
+ if (it == handles.end()) {
477
+ throw std::runtime_error("Invalid handle");
478
+ }
479
+
480
+ FFIResult result = json_eval_get_evaluated_schema_by_path(it->second, path.c_str(), skipLayout);
481
+
482
+ if (!result.success) {
483
+ std::string error = result.error ? result.error : "Unknown error";
484
+ json_eval_free_result(result);
485
+ throw std::runtime_error(error);
486
+ }
487
+
488
+ // Zero-copy: construct string directly from raw pointer
489
+ std::string resultStr;
490
+ if (result.data_ptr && result.data_len > 0) {
491
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
492
+ } else {
493
+ resultStr = "null";
494
+ }
495
+ json_eval_free_result(result);
496
+ return resultStr;
497
+ }, callback);
498
+ }
499
+
500
+ void JsonEvalBridge::getEvaluatedSchemaByPathsAsync(
501
+ const std::string& handleId,
502
+ const std::string& pathsJson,
503
+ bool skipLayout,
504
+ std::function<void(const std::string&, const std::string&)> callback
505
+ ) {
506
+ runAsync([handleId, pathsJson, skipLayout]() -> std::string {
507
+ std::lock_guard<std::mutex> lock(handlesMutex);
508
+ auto it = handles.find(handleId);
509
+ if (it == handles.end()) {
510
+ throw std::runtime_error("Invalid handle");
511
+ }
512
+
513
+ FFIResult result = json_eval_get_evaluated_schema_by_paths(it->second, pathsJson.c_str(), skipLayout);
514
+
515
+ if (!result.success) {
516
+ std::string error = result.error ? result.error : "Unknown error";
517
+ json_eval_free_result(result);
518
+ throw std::runtime_error(error);
519
+ }
520
+
521
+ // Zero-copy: construct string directly from raw pointer
522
+ std::string resultStr;
523
+ if (result.data_ptr && result.data_len > 0) {
524
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
525
+ } else {
526
+ resultStr = "{}";
527
+ }
528
+ json_eval_free_result(result);
529
+ return resultStr;
530
+ }, callback);
531
+ }
532
+
533
+ void JsonEvalBridge::getSchemaByPathAsync(
534
+ const std::string& handleId,
535
+ const std::string& path,
536
+ std::function<void(const std::string&, const std::string&)> callback
537
+ ) {
538
+ runAsync([handleId, path]() -> std::string {
539
+ std::lock_guard<std::mutex> lock(handlesMutex);
540
+ auto it = handles.find(handleId);
541
+ if (it == handles.end()) {
542
+ throw std::runtime_error("Invalid handle");
543
+ }
544
+
545
+ FFIResult result = json_eval_get_schema_by_path(it->second, path.c_str());
546
+
547
+ if (!result.success) {
548
+ std::string error = result.error ? result.error : "Unknown error";
549
+ json_eval_free_result(result);
550
+ throw std::runtime_error(error);
551
+ }
552
+
553
+ // Zero-copy: construct string directly from raw pointer
554
+ std::string resultStr;
555
+ if (result.data_ptr && result.data_len > 0) {
556
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
557
+ } else {
558
+ resultStr = "null";
559
+ }
560
+ json_eval_free_result(result);
561
+ return resultStr;
562
+ }, callback);
563
+ }
564
+
565
+ void JsonEvalBridge::getSchemaByPathsAsync(
566
+ const std::string& handleId,
567
+ const std::string& pathsJson,
568
+ std::function<void(const std::string&, const std::string&)> callback
569
+ ) {
570
+ runAsync([handleId, pathsJson]() -> std::string {
571
+ std::lock_guard<std::mutex> lock(handlesMutex);
572
+ auto it = handles.find(handleId);
573
+ if (it == handles.end()) {
574
+ throw std::runtime_error("Invalid handle");
575
+ }
576
+
577
+ FFIResult result = json_eval_get_schema_by_paths(it->second, pathsJson.c_str());
578
+
579
+ if (!result.success) {
580
+ std::string error = result.error ? result.error : "Unknown error";
581
+ json_eval_free_result(result);
582
+ throw std::runtime_error(error);
583
+ }
584
+
585
+ // Zero-copy: construct string directly from raw pointer
586
+ std::string resultStr;
587
+ if (result.data_ptr && result.data_len > 0) {
588
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
589
+ } else {
590
+ resultStr = "{}";
591
+ }
592
+ json_eval_free_result(result);
593
+ return resultStr;
594
+ }, callback);
595
+ }
596
+
597
+ void JsonEvalBridge::reloadSchemaAsync(
598
+ const std::string& handleId,
599
+ const std::string& schema,
600
+ const std::string& context,
601
+ const std::string& data,
602
+ std::function<void(const std::string&, const std::string&)> callback
603
+ ) {
604
+ runAsync([handleId, schema, context, data]() -> std::string {
605
+ std::lock_guard<std::mutex> lock(handlesMutex);
606
+ auto it = handles.find(handleId);
607
+ if (it == handles.end()) {
608
+ throw std::runtime_error("Invalid handle");
609
+ }
610
+
611
+ const char* ctx = context.empty() ? nullptr : context.c_str();
612
+ const char* dt = data.empty() ? nullptr : data.c_str();
613
+ FFIResult result = json_eval_reload_schema(it->second, schema.c_str(), ctx, dt);
614
+
615
+ if (!result.success) {
616
+ std::string error = result.error ? result.error : "Unknown error";
617
+ json_eval_free_result(result);
618
+ throw std::runtime_error(error);
619
+ }
620
+
621
+ json_eval_free_result(result);
622
+ return "{}";
623
+ }, callback);
624
+ }
625
+
626
+ void JsonEvalBridge::reloadSchemaMsgpackAsync(
627
+ const std::string& handleId,
628
+ const std::vector<uint8_t>& schemaMsgpack,
629
+ const std::string& context,
630
+ const std::string& data,
631
+ std::function<void(const std::string&, const std::string&)> callback
632
+ ) {
633
+ runAsync([handleId, schemaMsgpack, context, data]() -> std::string {
634
+ std::lock_guard<std::mutex> lock(handlesMutex);
635
+ auto it = handles.find(handleId);
636
+ if (it == handles.end()) {
637
+ throw std::runtime_error("Invalid handle");
638
+ }
639
+
640
+ const char* ctx = context.empty() ? nullptr : context.c_str();
641
+ const char* dt = data.empty() ? nullptr : data.c_str();
642
+ FFIResult result = json_eval_reload_schema_msgpack(
643
+ it->second,
644
+ schemaMsgpack.data(),
645
+ schemaMsgpack.size(),
646
+ ctx,
647
+ dt
648
+ );
649
+
650
+ if (!result.success) {
651
+ std::string error = result.error ? result.error : "Unknown error";
652
+ json_eval_free_result(result);
653
+ throw std::runtime_error(error);
654
+ }
655
+
656
+ json_eval_free_result(result);
657
+ return "{}";
658
+ }, callback);
659
+ }
660
+
661
+ void JsonEvalBridge::reloadSchemaFromCacheAsync(
662
+ const std::string& handleId,
663
+ const std::string& cacheKey,
664
+ const std::string& context,
665
+ const std::string& data,
666
+ std::function<void(const std::string&, const std::string&)> callback
667
+ ) {
668
+ runAsync([handleId, cacheKey, context, data]() -> std::string {
669
+ std::lock_guard<std::mutex> lock(handlesMutex);
670
+ auto it = handles.find(handleId);
671
+ if (it == handles.end()) {
672
+ throw std::runtime_error("Invalid handle");
673
+ }
674
+
675
+ const char* ctx = context.empty() ? nullptr : context.c_str();
676
+ const char* dt = data.empty() ? nullptr : data.c_str();
677
+ FFIResult result = json_eval_reload_schema_from_cache(
678
+ it->second,
679
+ cacheKey.c_str(),
680
+ ctx,
681
+ dt
682
+ );
683
+
684
+ if (!result.success) {
685
+ std::string error = result.error ? result.error : "Unknown error";
686
+ json_eval_free_result(result);
687
+ throw std::runtime_error(error);
688
+ }
689
+
690
+ json_eval_free_result(result);
691
+ return "{}";
692
+ }, callback);
693
+ }
694
+
695
+ void JsonEvalBridge::cacheStatsAsync(
696
+ const std::string& handleId,
697
+ std::function<void(const std::string&, const std::string&)> callback
698
+ ) {
699
+ runAsync([handleId]() -> std::string {
700
+ std::lock_guard<std::mutex> lock(handlesMutex);
701
+ auto it = handles.find(handleId);
702
+ if (it == handles.end()) {
703
+ throw std::runtime_error("Invalid handle");
704
+ }
705
+
706
+ FFIResult result = json_eval_cache_stats(it->second);
707
+
708
+ if (!result.success) {
709
+ std::string error = result.error ? result.error : "Unknown error";
710
+ json_eval_free_result(result);
711
+ throw std::runtime_error(error);
712
+ }
713
+
714
+ // Zero-copy: construct string directly from raw pointer
715
+ std::string resultStr;
716
+ if (result.data_ptr && result.data_len > 0) {
717
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
718
+ } else {
719
+ resultStr = "{}";
720
+ }
721
+ json_eval_free_result(result);
722
+ return resultStr;
723
+ }, callback);
724
+ }
725
+
726
+ void JsonEvalBridge::clearCacheAsync(
727
+ const std::string& handleId,
728
+ std::function<void(const std::string&, const std::string&)> callback
729
+ ) {
730
+ runAsync([handleId]() -> std::string {
731
+ std::lock_guard<std::mutex> lock(handlesMutex);
732
+ auto it = handles.find(handleId);
733
+ if (it == handles.end()) {
734
+ throw std::runtime_error("Invalid handle");
735
+ }
736
+
737
+ FFIResult result = json_eval_clear_cache(it->second);
738
+
739
+ if (!result.success) {
740
+ std::string error = result.error ? result.error : "Unknown error";
741
+ json_eval_free_result(result);
742
+ throw std::runtime_error(error);
743
+ }
744
+
745
+ json_eval_free_result(result);
746
+ return "{}";
747
+ }, callback);
748
+ }
749
+
750
+ void JsonEvalBridge::cacheLenAsync(
751
+ const std::string& handleId,
752
+ std::function<void(const std::string&, const std::string&)> callback
753
+ ) {
754
+ runAsync([handleId]() -> std::string {
755
+ std::lock_guard<std::mutex> lock(handlesMutex);
756
+ auto it = handles.find(handleId);
757
+ if (it == handles.end()) {
758
+ throw std::runtime_error("Invalid handle");
759
+ }
760
+
761
+ FFIResult result = json_eval_cache_len(it->second);
762
+
763
+ if (!result.success) {
764
+ std::string error = result.error ? result.error : "Unknown error";
765
+ json_eval_free_result(result);
766
+ throw std::runtime_error(error);
767
+ }
768
+
769
+ // Zero-copy: construct string directly from raw pointer
770
+ std::string resultStr;
771
+ if (result.data_ptr && result.data_len > 0) {
772
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
773
+ } else {
774
+ resultStr = "0";
775
+ }
776
+ json_eval_free_result(result);
777
+ return resultStr;
778
+ }, callback);
779
+ }
780
+
781
+ void JsonEvalBridge::enableCacheAsync(
782
+ const std::string& handleId,
783
+ std::function<void(const std::string&, const std::string&)> callback
784
+ ) {
785
+ runAsync([handleId]() -> std::string {
786
+ std::lock_guard<std::mutex> lock(handlesMutex);
787
+ auto it = handles.find(handleId);
788
+ if (it == handles.end()) {
789
+ throw std::runtime_error("Invalid handle");
790
+ }
791
+
792
+ FFIResult result = json_eval_enable_cache(it->second);
793
+
794
+ if (!result.success) {
795
+ std::string error = result.error ? result.error : "Unknown error";
796
+ json_eval_free_result(result);
797
+ throw std::runtime_error(error);
798
+ }
799
+
800
+ json_eval_free_result(result);
801
+ return "";
802
+ }, callback);
803
+ }
804
+
805
+ void JsonEvalBridge::disableCacheAsync(
806
+ const std::string& handleId,
807
+ std::function<void(const std::string&, const std::string&)> callback
808
+ ) {
809
+ runAsync([handleId]() -> std::string {
810
+ std::lock_guard<std::mutex> lock(handlesMutex);
811
+ auto it = handles.find(handleId);
812
+ if (it == handles.end()) {
813
+ throw std::runtime_error("Invalid handle");
814
+ }
815
+
816
+ FFIResult result = json_eval_disable_cache(it->second);
817
+
818
+ if (!result.success) {
819
+ std::string error = result.error ? result.error : "Unknown error";
820
+ json_eval_free_result(result);
821
+ throw std::runtime_error(error);
822
+ }
823
+
824
+ json_eval_free_result(result);
825
+ return "";
826
+ }, callback);
827
+ }
828
+
829
+ bool JsonEvalBridge::isCacheEnabled(const std::string& handleId) {
830
+ std::lock_guard<std::mutex> lock(handlesMutex);
831
+ auto it = handles.find(handleId);
832
+ if (it == handles.end()) {
833
+ return false;
834
+ }
835
+
836
+ int result = json_eval_is_cache_enabled(it->second);
837
+ return result != 0;
838
+ }
839
+
840
+ void JsonEvalBridge::resolveLayoutAsync(
841
+ const std::string& handleId,
842
+ bool evaluate,
843
+ std::function<void(const std::string&, const std::string&)> callback
844
+ ) {
845
+ runAsync([handleId, evaluate]() -> std::string {
846
+ std::lock_guard<std::mutex> lock(handlesMutex);
847
+ auto it = handles.find(handleId);
848
+ if (it == handles.end()) {
849
+ throw std::runtime_error("Invalid handle");
850
+ }
851
+
852
+ FFIResult result = json_eval_resolve_layout(it->second, evaluate);
853
+
854
+ if (!result.success) {
855
+ std::string error = result.error ? result.error : "Unknown error";
856
+ json_eval_free_result(result);
857
+ throw std::runtime_error(error);
858
+ }
859
+
860
+ json_eval_free_result(result);
861
+ return "{}";
862
+ }, callback);
863
+ }
864
+
865
+ void JsonEvalBridge::compileAndRunLogicAsync(
866
+ const std::string& handleId,
867
+ const std::string& logicStr,
868
+ const std::string& data,
869
+ const std::string& context,
870
+ std::function<void(const std::string&, const std::string&)> callback
871
+ ) {
872
+ runAsync([handleId, logicStr, data, context]() -> std::string {
873
+ std::lock_guard<std::mutex> lock(handlesMutex);
874
+ auto it = handles.find(handleId);
875
+ if (it == handles.end()) {
876
+ throw std::runtime_error("Invalid handle");
877
+ }
878
+
879
+ const char* dataPtr = data.empty() ? nullptr : data.c_str();
880
+ const char* contextPtr = context.empty() ? nullptr : context.c_str();
881
+ FFIResult result = json_eval_compile_and_run_logic(it->second, logicStr.c_str(), dataPtr, contextPtr);
882
+
883
+ if (!result.success) {
884
+ std::string error = result.error ? result.error : "Unknown error";
885
+ json_eval_free_result(result);
886
+ throw std::runtime_error(error);
887
+ }
888
+
889
+ // Zero-copy: construct string directly from raw pointer
890
+ std::string resultStr;
891
+ if (result.data_ptr && result.data_len > 0) {
892
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
893
+ } else {
894
+ resultStr = "null";
895
+ }
896
+ json_eval_free_result(result);
897
+ return resultStr;
898
+ }, callback);
899
+ }
900
+
901
+ void JsonEvalBridge::validatePathsAsync(
902
+ const std::string& handleId,
903
+ const std::string& data,
904
+ const std::string& context,
905
+ const std::string& pathsJson,
906
+ std::function<void(const std::string&, const std::string&)> callback
907
+ ) {
908
+ runAsync([handleId, data, context, pathsJson]() -> std::string {
909
+ std::lock_guard<std::mutex> lock(handlesMutex);
910
+ auto it = handles.find(handleId);
911
+ if (it == handles.end()) {
912
+ throw std::runtime_error("Invalid handle");
913
+ }
914
+
915
+ const char* ctx = context.empty() ? nullptr : context.c_str();
916
+ const char* paths = pathsJson.empty() ? nullptr : pathsJson.c_str();
917
+ FFIResult result = json_eval_validate_paths(it->second, data.c_str(), ctx, paths);
918
+
919
+ if (!result.success) {
920
+ std::string error = result.error ? result.error : "Unknown error";
921
+ json_eval_free_result(result);
922
+ throw std::runtime_error(error);
923
+ }
924
+
925
+ // Zero-copy: construct string directly from raw pointer
926
+ std::string resultStr;
927
+ if (result.data_ptr && result.data_len > 0) {
928
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
929
+ } else {
930
+ resultStr = "{}";
931
+ }
932
+ json_eval_free_result(result);
933
+ return resultStr;
934
+ }, callback);
935
+ }
936
+
937
+ // ============================================================================
938
+ // Subform Methods
939
+ // ============================================================================
940
+
941
+ void JsonEvalBridge::evaluateSubformAsync(
942
+ const std::string& handleId,
943
+ const std::string& subformPath,
944
+ const std::string& data,
945
+ const std::string& context,
946
+ std::function<void(const std::string&, const std::string&)> callback
947
+ ) {
948
+ runAsync([handleId, subformPath, data, context]() -> std::string {
949
+ std::lock_guard<std::mutex> lock(handlesMutex);
950
+ auto it = handles.find(handleId);
951
+ if (it == handles.end()) {
952
+ throw std::runtime_error("Invalid handle");
953
+ }
954
+
955
+ const char* ctx = context.empty() ? nullptr : context.c_str();
956
+ FFIResult result = json_eval_evaluate_subform(it->second, subformPath.c_str(), data.c_str(), ctx);
957
+
958
+ if (!result.success) {
959
+ std::string error = result.error ? result.error : "Unknown error";
960
+ json_eval_free_result(result);
961
+ throw std::runtime_error(error);
962
+ }
963
+
964
+ json_eval_free_result(result);
965
+ return "{}";
966
+ }, callback);
967
+ }
968
+
969
+ void JsonEvalBridge::validateSubformAsync(
970
+ const std::string& handleId,
971
+ const std::string& subformPath,
972
+ const std::string& data,
973
+ const std::string& context,
974
+ std::function<void(const std::string&, const std::string&)> callback
975
+ ) {
976
+ runAsync([handleId, subformPath, data, context]() -> std::string {
977
+ std::lock_guard<std::mutex> lock(handlesMutex);
978
+ auto it = handles.find(handleId);
979
+ if (it == handles.end()) {
980
+ throw std::runtime_error("Invalid handle");
981
+ }
982
+
983
+ const char* ctx = context.empty() ? nullptr : context.c_str();
984
+ FFIResult result = json_eval_validate_subform(it->second, subformPath.c_str(), data.c_str(), ctx);
985
+
986
+ if (!result.success) {
987
+ std::string error = result.error ? result.error : "Unknown error";
988
+ json_eval_free_result(result);
989
+ throw std::runtime_error(error);
990
+ }
991
+
992
+ std::string resultStr;
993
+ if (result.data_ptr && result.data_len > 0) {
994
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
995
+ } else {
996
+ resultStr = "{\"hasError\":false,\"errors\":[]}";
997
+ }
998
+ json_eval_free_result(result);
999
+ return resultStr;
1000
+ }, callback);
1001
+ }
1002
+
1003
+ void JsonEvalBridge::evaluateDependentsSubformAsync(
1004
+ const std::string& handleId,
1005
+ const std::string& subformPath,
1006
+ const std::string& changedPath,
1007
+ const std::string& data,
1008
+ const std::string& context,
1009
+ std::function<void(const std::string&, const std::string&)> callback
1010
+ ) {
1011
+ runAsync([handleId, subformPath, changedPath, data, context]() -> std::string {
1012
+ std::lock_guard<std::mutex> lock(handlesMutex);
1013
+ auto it = handles.find(handleId);
1014
+ if (it == handles.end()) {
1015
+ throw std::runtime_error("Invalid handle");
1016
+ }
1017
+
1018
+ const char* dt = data.empty() ? nullptr : data.c_str();
1019
+ const char* ctx = context.empty() ? nullptr : context.c_str();
1020
+ FFIResult result = json_eval_evaluate_dependents_subform(it->second, subformPath.c_str(), changedPath.c_str(), dt, ctx);
1021
+
1022
+ if (!result.success) {
1023
+ std::string error = result.error ? result.error : "Unknown error";
1024
+ json_eval_free_result(result);
1025
+ throw std::runtime_error(error);
1026
+ }
1027
+
1028
+ std::string resultStr;
1029
+ if (result.data_ptr && result.data_len > 0) {
1030
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1031
+ } else {
1032
+ resultStr = "[]";
1033
+ }
1034
+ json_eval_free_result(result);
1035
+ return resultStr;
1036
+ }, callback);
1037
+ }
1038
+
1039
+ void JsonEvalBridge::resolveLayoutSubformAsync(
1040
+ const std::string& handleId,
1041
+ const std::string& subformPath,
1042
+ bool evaluate,
1043
+ std::function<void(const std::string&, const std::string&)> callback
1044
+ ) {
1045
+ runAsync([handleId, subformPath, evaluate]() -> std::string {
1046
+ std::lock_guard<std::mutex> lock(handlesMutex);
1047
+ auto it = handles.find(handleId);
1048
+ if (it == handles.end()) {
1049
+ throw std::runtime_error("Invalid handle");
1050
+ }
1051
+
1052
+ FFIResult result = json_eval_resolve_layout_subform(it->second, subformPath.c_str(), evaluate);
1053
+
1054
+ if (!result.success) {
1055
+ std::string error = result.error ? result.error : "Unknown error";
1056
+ json_eval_free_result(result);
1057
+ throw std::runtime_error(error);
1058
+ }
1059
+
1060
+ json_eval_free_result(result);
1061
+ return "{}";
1062
+ }, callback);
1063
+ }
1064
+
1065
+ void JsonEvalBridge::getEvaluatedSchemaSubformAsync(
1066
+ const std::string& handleId,
1067
+ const std::string& subformPath,
1068
+ bool resolveLayout,
1069
+ std::function<void(const std::string&, const std::string&)> callback
1070
+ ) {
1071
+ runAsync([handleId, subformPath, resolveLayout]() -> std::string {
1072
+ std::lock_guard<std::mutex> lock(handlesMutex);
1073
+ auto it = handles.find(handleId);
1074
+ if (it == handles.end()) {
1075
+ throw std::runtime_error("Invalid handle");
1076
+ }
1077
+
1078
+ FFIResult result = json_eval_get_evaluated_schema_subform(it->second, subformPath.c_str(), resolveLayout);
1079
+
1080
+ if (!result.success) {
1081
+ std::string error = result.error ? result.error : "Unknown error";
1082
+ json_eval_free_result(result);
1083
+ throw std::runtime_error(error);
1084
+ }
1085
+
1086
+ std::string resultStr;
1087
+ if (result.data_ptr && result.data_len > 0) {
1088
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1089
+ } else {
1090
+ resultStr = "{}";
1091
+ }
1092
+ json_eval_free_result(result);
1093
+ return resultStr;
1094
+ }, callback);
1095
+ }
1096
+
1097
+ void JsonEvalBridge::getSchemaValueSubformAsync(
1098
+ const std::string& handleId,
1099
+ const std::string& subformPath,
1100
+ std::function<void(const std::string&, const std::string&)> callback
1101
+ ) {
1102
+ runAsync([handleId, subformPath]() -> std::string {
1103
+ std::lock_guard<std::mutex> lock(handlesMutex);
1104
+ auto it = handles.find(handleId);
1105
+ if (it == handles.end()) {
1106
+ throw std::runtime_error("Invalid handle");
1107
+ }
1108
+
1109
+ FFIResult result = json_eval_get_schema_value_subform(it->second, subformPath.c_str());
1110
+
1111
+ if (!result.success) {
1112
+ std::string error = result.error ? result.error : "Unknown error";
1113
+ json_eval_free_result(result);
1114
+ throw std::runtime_error(error);
1115
+ }
1116
+
1117
+ std::string resultStr;
1118
+ if (result.data_ptr && result.data_len > 0) {
1119
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1120
+ } else {
1121
+ resultStr = "{}";
1122
+ }
1123
+ json_eval_free_result(result);
1124
+ return resultStr;
1125
+ }, callback);
1126
+ }
1127
+
1128
+ void JsonEvalBridge::getEvaluatedSchemaWithoutParamsSubformAsync(
1129
+ const std::string& handleId,
1130
+ const std::string& subformPath,
1131
+ bool resolveLayout,
1132
+ std::function<void(const std::string&, const std::string&)> callback
1133
+ ) {
1134
+ runAsync([handleId, subformPath, resolveLayout]() -> std::string {
1135
+ std::lock_guard<std::mutex> lock(handlesMutex);
1136
+ auto it = handles.find(handleId);
1137
+ if (it == handles.end()) {
1138
+ throw std::runtime_error("Invalid handle");
1139
+ }
1140
+
1141
+ FFIResult result = json_eval_get_evaluated_schema_without_params_subform(it->second, subformPath.c_str(), resolveLayout);
1142
+
1143
+ if (!result.success) {
1144
+ std::string error = result.error ? result.error : "Unknown error";
1145
+ json_eval_free_result(result);
1146
+ throw std::runtime_error(error);
1147
+ }
1148
+
1149
+ std::string resultStr;
1150
+ if (result.data_ptr && result.data_len > 0) {
1151
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1152
+ } else {
1153
+ resultStr = "{}";
1154
+ }
1155
+ json_eval_free_result(result);
1156
+ return resultStr;
1157
+ }, callback);
1158
+ }
1159
+
1160
+ void JsonEvalBridge::getEvaluatedSchemaByPathSubformAsync(
1161
+ const std::string& handleId,
1162
+ const std::string& subformPath,
1163
+ const std::string& schemaPath,
1164
+ bool skipLayout,
1165
+ std::function<void(const std::string&, const std::string&)> callback
1166
+ ) {
1167
+ runAsync([handleId, subformPath, schemaPath, skipLayout]() -> std::string {
1168
+ std::lock_guard<std::mutex> lock(handlesMutex);
1169
+ auto it = handles.find(handleId);
1170
+ if (it == handles.end()) {
1171
+ throw std::runtime_error("Invalid handle");
1172
+ }
1173
+
1174
+ FFIResult result = json_eval_get_evaluated_schema_by_path_subform(it->second, subformPath.c_str(), schemaPath.c_str(), skipLayout);
1175
+
1176
+ if (!result.success) {
1177
+ std::string error = result.error ? result.error : "Unknown error";
1178
+ json_eval_free_result(result);
1179
+ throw std::runtime_error(error);
1180
+ }
1181
+
1182
+ std::string resultStr;
1183
+ if (result.data_ptr && result.data_len > 0) {
1184
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1185
+ } else {
1186
+ resultStr = "null";
1187
+ }
1188
+ json_eval_free_result(result);
1189
+ return resultStr;
1190
+ }, callback);
1191
+ }
1192
+
1193
+ void JsonEvalBridge::getEvaluatedSchemaByPathsSubformAsync(
1194
+ const std::string& handleId,
1195
+ const std::string& subformPath,
1196
+ const std::string& schemaPathsJson,
1197
+ bool skipLayout,
1198
+ std::function<void(const std::string&, const std::string&)> callback
1199
+ ) {
1200
+ runAsync([handleId, subformPath, schemaPathsJson, skipLayout]() -> std::string {
1201
+ std::lock_guard<std::mutex> lock(handlesMutex);
1202
+ auto it = handles.find(handleId);
1203
+ if (it == handles.end()) {
1204
+ throw std::runtime_error("Invalid handle");
1205
+ }
1206
+
1207
+ FFIResult result = json_eval_get_evaluated_schema_by_paths_subform(it->second, subformPath.c_str(), schemaPathsJson.c_str(), skipLayout);
1208
+
1209
+ if (!result.success) {
1210
+ std::string error = result.error ? result.error : "Unknown error";
1211
+ json_eval_free_result(result);
1212
+ throw std::runtime_error(error);
1213
+ }
1214
+
1215
+ std::string resultStr;
1216
+ if (result.data_ptr && result.data_len > 0) {
1217
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1218
+ } else {
1219
+ resultStr = "{}";
1220
+ }
1221
+ json_eval_free_result(result);
1222
+ return resultStr;
1223
+ }, callback);
1224
+ }
1225
+
1226
+ void JsonEvalBridge::getSubformPathsAsync(
1227
+ const std::string& handleId,
1228
+ std::function<void(const std::string&, const std::string&)> callback
1229
+ ) {
1230
+ runAsync([handleId]() -> std::string {
1231
+ std::lock_guard<std::mutex> lock(handlesMutex);
1232
+ auto it = handles.find(handleId);
1233
+ if (it == handles.end()) {
1234
+ throw std::runtime_error("Invalid handle");
1235
+ }
1236
+
1237
+ FFIResult result = json_eval_get_subform_paths(it->second);
1238
+
1239
+ if (!result.success) {
1240
+ std::string error = result.error ? result.error : "Unknown error";
1241
+ json_eval_free_result(result);
1242
+ throw std::runtime_error(error);
1243
+ }
1244
+
1245
+ std::string resultStr;
1246
+ if (result.data_ptr && result.data_len > 0) {
1247
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1248
+ } else {
1249
+ resultStr = "[]";
1250
+ }
1251
+ json_eval_free_result(result);
1252
+ return resultStr;
1253
+ }, callback);
1254
+ }
1255
+
1256
+ void JsonEvalBridge::getSchemaByPathSubformAsync(
1257
+ const std::string& handleId,
1258
+ const std::string& subformPath,
1259
+ const std::string& schemaPath,
1260
+ std::function<void(const std::string&, const std::string&)> callback
1261
+ ) {
1262
+ runAsync([handleId, subformPath, schemaPath]() -> std::string {
1263
+ std::lock_guard<std::mutex> lock(handlesMutex);
1264
+ auto it = handles.find(handleId);
1265
+ if (it == handles.end()) {
1266
+ throw std::runtime_error("Invalid handle");
1267
+ }
1268
+
1269
+ FFIResult result = json_eval_get_schema_by_path_subform(it->second, subformPath.c_str(), schemaPath.c_str());
1270
+
1271
+ if (!result.success) {
1272
+ std::string error = result.error ? result.error : "Unknown error";
1273
+ json_eval_free_result(result);
1274
+ throw std::runtime_error(error);
1275
+ }
1276
+
1277
+ std::string resultStr;
1278
+ if (result.data_ptr && result.data_len > 0) {
1279
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1280
+ } else {
1281
+ resultStr = "null";
1282
+ }
1283
+ json_eval_free_result(result);
1284
+ return resultStr;
1285
+ }, callback);
1286
+ }
1287
+
1288
+ void JsonEvalBridge::getSchemaByPathsSubformAsync(
1289
+ const std::string& handleId,
1290
+ const std::string& subformPath,
1291
+ const std::string& schemaPathsJson,
1292
+ std::function<void(const std::string&, const std::string&)> callback
1293
+ ) {
1294
+ runAsync([handleId, subformPath, schemaPathsJson]() -> std::string {
1295
+ std::lock_guard<std::mutex> lock(handlesMutex);
1296
+ auto it = handles.find(handleId);
1297
+ if (it == handles.end()) {
1298
+ throw std::runtime_error("Invalid handle");
1299
+ }
1300
+
1301
+ FFIResult result = json_eval_get_schema_by_paths_subform(it->second, subformPath.c_str(), schemaPathsJson.c_str());
1302
+
1303
+ if (!result.success) {
1304
+ std::string error = result.error ? result.error : "Unknown error";
1305
+ json_eval_free_result(result);
1306
+ throw std::runtime_error(error);
1307
+ }
1308
+
1309
+ std::string resultStr;
1310
+ if (result.data_ptr && result.data_len > 0) {
1311
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1312
+ } else {
1313
+ resultStr = "{}";
1314
+ }
1315
+ json_eval_free_result(result);
1316
+ return resultStr;
1317
+ }, callback);
1318
+ }
1319
+
1320
+ void JsonEvalBridge::hasSubformAsync(
1321
+ const std::string& handleId,
1322
+ const std::string& subformPath,
1323
+ std::function<void(const std::string&, const std::string&)> callback
1324
+ ) {
1325
+ runAsync([handleId, subformPath]() -> std::string {
1326
+ std::lock_guard<std::mutex> lock(handlesMutex);
1327
+ auto it = handles.find(handleId);
1328
+ if (it == handles.end()) {
1329
+ throw std::runtime_error("Invalid handle");
1330
+ }
1331
+
1332
+ FFIResult result = json_eval_has_subform(it->second, subformPath.c_str());
1333
+
1334
+ if (!result.success) {
1335
+ std::string error = result.error ? result.error : "Unknown error";
1336
+ json_eval_free_result(result);
1337
+ throw std::runtime_error(error);
1338
+ }
1339
+
1340
+ std::string resultStr;
1341
+ if (result.data_ptr && result.data_len > 0) {
1342
+ resultStr.assign(reinterpret_cast<const char*>(result.data_ptr), result.data_len);
1343
+ } else {
1344
+ resultStr = "false";
1345
+ }
1346
+ json_eval_free_result(result);
1347
+ return resultStr;
1348
+ }, callback);
1349
+ }
1350
+
1351
+ void JsonEvalBridge::dispose(const std::string& handleId) {
1352
+ std::lock_guard<std::mutex> lock(handlesMutex);
1353
+ auto it = handles.find(handleId);
1354
+ if (it != handles.end()) {
1355
+ json_eval_free(it->second);
1356
+ handles.erase(it);
1357
+ }
1358
+ }
1359
+
1360
+ std::string JsonEvalBridge::version() {
1361
+ const char* ver = json_eval_version();
1362
+ // Version string is static in Rust, no need to free it
1363
+ return ver ? ver : "unknown";
1364
+ }
1365
+
1366
+ } // namespace jsoneval