1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
/*
* Copyright (c) 2025-2026 Anton Kundenko <singaraiona@gmail.com>
* All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
extern "C" RAY_VERSION_MAJOR
/* Packed version number: 0xMMmmpp (MM=major, mm=minor, pp=patch) */
/* Compile-time version check: true if lib version >= (major, minor, patch) */
/* Runtime version query */
int ;
int ;
int ;
const char* ;
/* The commit this library was built from, as its build saw it ("unknown"
* outside a git checkout). A compile-time constant: safe to call before
* any runtime exists. */
const char* ;
/* == */
/* Unified dictionary-encoded string column (adaptive width) */
/* Variable-length string column (inline + pool) */
/* Compound types */
/* Function types (Rayforce-compatible) */
/* == */
typedef enum ray_err_t;
/* == */
/* Symbol-resolution domain (src/table/domain.h): every RAY_SYM vector
* carries a non-NULL pointer to one — either the immortal runtime
* singleton (global intern table) or a refcounted mmapped symfile. */
;
/* One file mapping shared by more than one block (src/mem/heap.h): a mapped
* string column and its pool live in the same region, so neither can end it
* alone. Held by the pool at aux[8..15] under mmod 3. */
;
typedef union ray_t ray_t;
/* Global null singleton — always valid, retain/release are no-ops (ARENA flag) */
extern ray_t __ray_null;
/* A value position (an eval'd / builtin-returned ray_t*) is never a bare C NULL —
* value-null is always RAY_NULL_OBJ. Assert that invariant in debug/ASan builds;
* compile to nothing in release. Placed BEFORE any null test that may deref,
* because RAY_ATOM_IS_NULL/ray_atom_is_null_fn deref x->type on non-singleton input. */
/* Kept live in the hardened cloud tier too (not just DEBUG): the check is a
* single pointer compare, and a stray C NULL in a value position is exactly
* the class of corruption that must fail fast — routed through the crash
* handler's SIGABRT backtrace — rather than segfault deep in a kernel. */
/* Global last-resort OOM error sentinel — returned by ray_error when its
* own ray_alloc fails (deep OOM, e.g. heap can't even satisfy the 32-byte
* error header). ARENA-flagged like RAY_NULL_OBJ so retain/release are
* no-ops; slen=3 / sdata="oom" so RAY_IS_ERR() and ray_err_code() both
* work without touching the heap. Carries no per-VM message — we have
* no heap to format one into. Without this fallback, hard OOM would
* silently bypass every `if (RAY_IS_ERR(x)) return x;` guard upstream. */
extern ray_t __ray_oom;
/* Error object creation (defined in core/runtime.c) */
ray_t* ;
const char* ;
ray_err_t ;
const char* ;
/* Free a RAY_ERROR object. ray_release() is a deliberate no-op for
* error ray_t* (see src/mem/cow.c), so callers that hold the sole
* reference and want the block reclaimed must use this helper instead —
* otherwise the error leaks until heap teardown. */
void ;
/* == */
/* Element type sizes indexed by type tag — covers all uint8_t values.
* Only types 1-14 (vectors) have non-zero entries. */
extern const uint8_t ray_type_sizes;
/* Out-of-line slice deref: keeps the hot path of ray_data_fn (a single
* load + return) trivially inlinable while the rare slice arm lives in
* one TU (vec.c) — avoids N inline instantiations of the slice branch
* across every translation unit that includes this header. */
void* ;
static inline void*
/* == */
/* The immortal runtime domain singleton wrapping the global intern table.
* Full domain API lives in src/table/domain.h. */
struct ray_sym_domain_s* ;
/* Resolution domain of a RAY_SYM vector. Slices don't carry a domain of
* their own — follow slice_parent, the same walk ray_data_fn performs.
* Defensively returns the runtime singleton if the field is zero (e.g. a
* producer that builds SYM headers by hand); uniform non-NULL guarantee
* for consumers. */
static inline struct ray_sym_domain_s*
/* Domain resolution primitives (full API + docs: src/table/domain.h).
* Declared here so the inline cell-resolution helpers next to
* ray_read_sym (src/table/sym.h) compile without internal headers.
* str: borrowed string atom for position `pos` (NULL if out of range);
* find: position of the bytes in the domain, -1 if absent. */
ray_t* ;
int64_t ;
/* Entry count, and the position → runtime-intern-id LUT (NULL for the
* runtime domain — ids pass through; for FILE domains the FIRST request
* interns the vocabulary sequentially: obtain the LUT BEFORE handing
* cell ids to ray_pool_dispatch workers). Docs: src/table/domain.h. */
int64_t ;
const int64_t* ;
/* An output SYM vector built by COPYING cell ids from `in` (group keys,
* filtered selections) must resolve over the same dictionary: release
* out's previous non-singleton domain ref, copy the pointer, retain the
* new non-singleton. No-op unless both are RAY_SYM vectors (and never
* touches slice headers — their aux bytes are parent/offset). Defined
* in src/vec/vec.c. */
void ;
/* == */
int8_t ;
uint8_t ;
int64_t ;
double ;
int64_t ;
/* == */
ray_t* ;
/* NOTE: ray_free supports cross-thread free via foreign_blocks list.
* Blocks freed from a non-owning thread are deferred and coalesced
* when the owning heap flushes foreign blocks. */
void ;
/* ===== Raw buffer allocator (buddy-backed, no libc malloc) =====
* malloc/calloc/realloc/free replacements for plain byte/scalar buffers that
* are NOT ray_t values — backed by the tuned slab/buddy heap (fast for the many
* small per-partition allocations the agg engine makes), thread-safe, with
* cross-thread free. ray_alloc_raw returns uninitialised memory; ray_calloc_raw
* zeroes it. Free with ray_free_raw, grow with ray_realloc_raw. */
void* ;
void* ;
void* ;
void ;
/* == */
int64_t ; /* total physical RAM in bytes (informational) */
int64_t ; /* RAM this process may use: min(physical RAM,
* container/cgroup limit); the default anon watermark */
/* ===== Interrupt API =====
* Long-running queries poll ray_interrupted() at morsel granularity
* and bail out with a "cancel" error. The REPL's SIGINT handler wires
* Ctrl-C to ray_request_interrupt(); embedders can call it from their
* own signal handlers or cancellation threads. */
void ;
void ;
bool ;
/* ===== Progress API =====
* Pull-based, main-thread only. Worker threads never touch progress
* state. The executor calls ray_progress_update() at natural sync
* points (between ops, after pool dispatches, at pivot phase
* boundaries); the update only fires the user callback once the
* query has been running for at least min_ms and at most once per
* tick_interval_ms. Embedders register a callback to visualize
* long-running queries; leaving it unset has zero runtime cost. */
typedef struct ray_progress_t;
typedef void ;
/* Register a progress callback. Set cb=NULL to disable. min_ms is the
* show-after threshold: queries finishing under it fire
* zero callbacks. tick_interval_ms throttles updates once active. */
void ;
/* Update progress state. Safe to call from the main thread only.
* phase/op_name may be NULL to keep the previous value. Counters
* always overwrite — 0 is a valid "starting fresh" value. Fires the
* registered callback if the show-after and tick-interval gates pass. */
void ;
/* Relabel without touching the counters — for wrappers like exec_node
* that only know which operator is about to run but not its rows. A
* subsequent ray_progress_update from inside the op will advance the
* counters; until then the renderer shows an indeterminate bar. */
void ;
/* Mark the end of the current query. Clears state and fires a final
* "100%" tick if the query ran long enough to have shown the bar. */
void ;
/* True iff a progress callback is registered. The executor gates arming the
* qstats PROGRESS bit on this, so all progress plumbing stays zero-cost when
* nothing is listening. */
bool ;
/* Pool-dispatch pump (main-thread only). ray_progress_dispatch_begin records a
* parallel dispatch's element total and baselines the shared qstats row
* counter; ray_progress_pump samples it and fires the throttled callback. The
* pool calls these from its claim-loop / spin-wait so every morsel-parallel op
* reports progress with no per-kernel changes. Both are no-ops with no callback. */
void ;
void ;
/* ===== Byte-metered span (main-thread only) =====
*
* An op made of several internal phases — each of which may run its own pool
* dispatch over a different element count — cannot report honest progress
* through the per-dispatch pump: every dispatch restarts at 0%, so the bar
* saws. A SPAN gives such an op one monotone axis (bytes of input) that all
* of its phases share.
*
* ray_progress_span_begin declares the axis (bytes_total, e.g. the file size).
* ray_progress_span_phase declares that whatever runs next occupies
* [base, base+len) of that axis: the dispatch pump maps its own 0..100% into
* that window instead of publishing raw row counts, and a serial phase can
* drive the same window directly with ray_progress_span_set. The published
* value never decreases. All are no-ops with no callback registered. */
void ;
void ;
void ;
void ;
/* == */
void ;
void ;
/* ===== Native footprint (foreign-runtime GC accounting) =====
*
* How many bytes of native memory a value stands for, in two well-defined
* senses, so an embedding runtime can charge its garbage collector for a
* wrapper that keeps a Rayforce value alive. Both are O(size of the value
* graph walked) and never allocate on the Rayforce heap.
*
* ray_shallow_bytes — what this value's own release gives back: the block
* the allocator committed for it (header + capacity — a buddy block is a
* power of two, a large "direct" block its exact page-rounded mapping) PLUS
* the private storage no public API hands out on its own and that only
* this value releases: a long string atom's payload, a GUID atom's payload,
* a string vector's pool, an attached accelerator index with its tables.
* A file-mapped column reports the length of its mapping (a splayed string
* column's region is charged to the column; the pool block inside it
* reports 0). Slices report only their own header block. Children that
* are values in their own right — list elements, table and dict slots,
* lambda parts, a slice's parent — are NOT included, so a table and its
* separately wrapped columns are never charged twice. Non-owning values
* report 0: the null and OOM singletons, arena-allocated values, borrowed
* blocks, an index that is a passenger in a column's mapping. A string
* pool shared by copy-on-write copies of one vector is charged to each
* copy. Symbol domains, lazy DAGs and opaque native handles (HNSW, graph)
* are outside the accounting.
*
* ray_retained_bytes — the shallow bytes of this value and of every value
* reachable from it through ownership edges (list elements, table and dict
* slots, lambda parts, slice parents, parted segments), each distinct block
* counted once. Sharing between the walked values is therefore not double
* counted, but two calls on two values that share children both report the
* shared part. Meant for diagnostics; drive GC pressure with the shallow
* figure.
*
* Errors are ordinary blocks (a RAY_ERROR reports its block). NULL → 0. */
size_t ;
size_t ;
/* == */
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
/* Current UTC wall-clock time as a RAY_TIMESTAMP value (ns since 2000-01-01).
* Shared "now as a timestamp" primitive — the single owner of the epoch
* conversion; callers must not re-derive it. */
int64_t ;
ray_t* ;
ray_t* ;
/* ===== Nullability and Null Sentinel Values =====
*
* Public nullability matrix:
*
* type family atom encoding vector encoding
* ---------------- ------------------------ ------------------------
* I16/I32/I64 width-correct NULL_* width-correct NULL_*
* DATE/TIME/TS width-correct NULL_* width-correct NULL_*
* F32/F64 NaN NaN
* GUID 16 all-zero bytes 16 all-zero bytes
* BOOL/U8 ray_typed_null aux bit non-nullable
* SYM/STR canonical empty value canonical empty value
*
* Empty SYM/STR values are their canonical in-band nulls. A requested typed
* or input null for either type collapses to that empty representation; the
* public null predicate recognizes it and vectors containing it acquire
* HAS_NULLS. Callers compare sentinel-backed payloads directly (for example
* `x == NULL_I64` or `x != x` for NaN). Temporal types reuse NULL_I32 or
* NULL_I64 according to storage width. */
/* Atom null check. RAY_NULL_OBJ is the untyped null singleton.
* Sentinel-backed atoms use payload comparison. BOOL/U8 typed-null atoms
* use the aux[0]&1 bit written by ray_typed_null. SYM/STR use their
* canonical in-band empty values (sym 0 / "") as null. */
static inline bool
/* == */
ray_t* ;
/* RAY_SYM index width — encoded in the lower 2 bits of the vector's
* `attrs` byte. Pick the smallest width that fits the destination
* symbol-table size; W64 is the safe default when growing globally. */
ray_t* ; /* RAY_SYM with adaptive width */
ray_t* ;
ray_t* ; /* one reserve + one memcpy */
ray_t* ;
void* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
/* Null bitmap ops */
void ;
ray_err_t ;
bool ;
/* == */
ray_t* ;
ray_t* ;
const char* ;
ray_t* ;
ray_t* ;
ray_t* ;
/* == */
const char* ;
size_t ;
int ;
/* == */
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
/* == */
ray_err_t ;
void ;
int64_t ;
int64_t ;
int64_t ;
ray_t* ;
uint32_t ;
/* Bytes of string storage the global symbol table holds (its arena). */
size_t ;
/* Borrow a snapshot of the sym → string array. Returns a pointer to
* the underlying ray_t** strings table along with its length; valid
* only while no concurrent ray_sym_intern occurs (i.e. read-only
* execution phases). Lock is taken once for the snapshot and dropped
* before return — caller may iterate freely. Both *out_strings and
* *out_count must be non-NULL. */
void ;
bool ;
/* Runtime dictionary snapshot — NOT table symfiles. ray_sym_save writes
* the whole process-global intern table to `path` (tmp + fsync + atomic
* rename, replacing whatever was there; single-writer contract);
* ray_sym_load restores it, requiring every entry to land at the id equal
* to its file position so ids from the saved session stay valid (see
* ray_runtime_create_with_sym). Stored tables do not use these: their
* symbols live in per-table symfiles managed by the storage layer. */
ray_err_t ;
ray_err_t ;
/* ===== Environment API =====
*
* Thread-safety: the environment is shared global state. Concurrent calls
* to ray_env_get() and ray_env_set() require external synchronization by
* the caller. */
ray_t* ;
ray_err_t ;
/* ===== Table API =====
*
* Every function here that takes a `ray_t* tbl` is total over ray_t: handed a
* value whose type is not RAY_TABLE — an atom, a vector, a dict, an error,
* NULL — none of them reads the argument's payload as table storage. An
* embedder holding one opaque ray_t* can call any of them without first
* establishing the type. What a wrong tag yields differs by return contract:
*
* ray_table_ncols / ray_table_nrows -> 0
* ray_table_col_name -> -1
* ray_table_schema / ray_table_get_col* -> NULL
* ray_table_set_col_name / ray_table_set_col_idx -> no-op
* ray_table_add_col -> typed "type" error
* ray_table_validate_rectangular -> typed "type" error
*
* ray_table_add_col consumes its `tbl` ref on every path, the error path
* included, so a wrong tag releases the argument exactly as a bad column does.
*
* The two that return a typed error are the ones to reach for when the
* distinction matters: the accessors answer 0/NULL indistinguishably from a
* genuinely empty table, so they cannot tell you *why* the answer was empty.
*/
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
int64_t ;
void ;
void ;
int64_t ;
int64_t ;
ray_t* ;
/* ===== Dict API =====
*
* A dict is a 2-pointer block (type=RAY_DICT, len=2) holding [keys, vals].
* Pair count is keys->len.
*
* keys: Either a typed vector (RAY_SYM / RAY_I64 / RAY_F64 / RAY_STR /
* RAY_GUID / RAY_DATE / RAY_TIME / RAY_TIMESTAMP / RAY_I32 /
* RAY_I16 / RAY_BOOL / RAY_U8 / RAY_F32) when every key shares
* one atom type, or a RAY_LIST of boxed atoms when keys are
* heterogeneous. Typed-vec lookup honors the keys' null bitmap
* so a null key never collides with a legitimate zero/sentinel.
* vals: Either a typed vector when every value shares one atom type,
* or a RAY_LIST otherwise (the form parsed from {…} literals,
* which keep value expressions unevaluated until probed).
*
* Layout matches RAY_TABLE; only the type tag and the contract on
* `vals` (a RAY_LIST of column vectors for tables) differ.
*/
ray_t* ; /* consumes both */
ray_t* ; /* borrowed */
ray_t* ; /* borrowed */
int64_t ; /* keys->len */
ray_t* ; /* owned, NULL if missing */
ray_t* ; /* COW; consumes d */
ray_t* ; /* COW; consumes d */
/* ===== Runtime + Rayfall Eval API =====
*
* Embedders build a runtime, optionally restoring a persisted symbol
* table, then evaluate Rayfall source strings against the global env.
*
* Tables and other ray_t* values can be exposed to Rayfall by interning
* a symbol name and binding via ray_env_set, then queried with
* ray_eval_str:
*
* ray_runtime_t* rt = ray_runtime_create_with_sym(".sym");
* int64_t name_id = ray_sym_intern("t", 1);
* ray_env_set(name_id, my_table); // rayforce retains
* ray_t* result = ray_eval_str("select count from t");
* if (RAY_IS_ERR(result)) { ... } else { ...; ray_release(result); }
* ray_runtime_destroy(rt);
*
* Single-runtime: only one ray_runtime_t may be live at a time in the
* same process. Creating a second without destroying the first is
* undefined. Symbols, env, and builtins are process-global; the
* runtime owns their lifetime. */
typedef struct ray_runtime_s ray_runtime_t;
/* Create a runtime with an empty symbol table. argc/argv are forwarded
* so embedders can hand off CLI flags; pass 0/NULL when not applicable. */
ray_runtime_t* ;
/* Create a runtime and pre-load the persisted symbol table at sym_path.
* Missing file or NULL is fine (symbols start empty). I/O or corrupt-
* file conditions are non-fatal: the runtime starts up and the caller
* can detect the issue via ray_runtime_create_with_sym_err if needed. */
ray_runtime_t* ;
/* As ray_runtime_create_with_sym, but writes the sym-load status to
* *out_sym_err. RAY_OK on success or absent file; non-zero on I/O,
* corrupt-file, or OOM during sym load. Pass NULL to ignore. */
ray_runtime_t* ;
/* Tear down the runtime: lang state, env, VMs, heap. Always pair with
* exactly one ray_runtime_create* call. */
void ;
/* ===== Host-Driven Event Loop API =====
*
* Embedders that own the runtime thread can attach a poll to the runtime,
* create listeners from Rayfall (for example `(.sys.listen 7701)`), and
* service IPC and Rayfall timers in bounded slices. The runtime borrows
* the poll: detach and destroy it before destroying the runtime. */
typedef struct ray_poll ray_poll_t;
ray_poll_t* ;
void ;
/* Mark IPC evaluations on connections subsequently created by poll as
* restricted (read-only). Existing connections keep their original mode.
* Call from the thread that owns poll before servicing the listener.
* A NULL poll is ignored. */
void ;
/* Run until ray_poll_exit is called. */
int64_t ;
/* Serve events and timers for at most timeout_ms milliseconds.
* A negative timeout preserves ray_poll_run's blocking behavior; zero
* performs one non-blocking drain. Returns 0 (or an exit code) normally
* and -1 when poll is NULL or the platform event queue fails. */
int64_t ;
void ;
/* The runtime borrows this pointer; pass NULL to detach it. */
void ;
void* ;
/* Parse and evaluate a Rayfall source string against the global env.
* Returns RAY_NULL_OBJ for successful void / null results, an error ray_t*
* on failure (test with RAY_IS_ERR and inspect with ray_err_code), or the
* result value otherwise. Caller owns the returned reference; release
* with ray_release. */
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
ray_t* ;
/* ===== IPC Client API =====
*
* Blocking client API for talking to a Rayforce IPC server. Handles are
* process-local integer slots returned by ray_ipc_connect and released by
* ray_ipc_close. ray_ipc_send performs a synchronous request/response
* exchange; ray_ipc_send_async sends a fire-and-forget frame. */
int64_t ;
void ;
ray_t* ;
/* As ray_ipc_send, bounded: timeout_ms > 0 caps the whole round trip.
* On expiry the connection is closed (on.close fires) and an `io` error
* is returned; timeout_ms <= 0 waits indefinitely, like ray_ipc_send. */
ray_t* ;
ray_err_t ;
ray_t* ;
/* ===== Append-Only Log (AOF) API =====
*
* Embeddable durable event log for host applications: opaque payloads,
* monotonic contiguous LSNs, explicit commit barriers, segment rotation,
* crash recovery. Independent of the ray_runtime_t lifecycle — usable
* before ray_runtime_create and after ray_runtime_destroy.
*
* Durability model: ray_aof_append() buffers and returns the reserved
* LSN; ray_aof_commit() writes a commit frame into the stream and
* fsyncs — every append issued before it is durable and becomes
* observable once it returns RAY_OK. Scans deliver only records that
* precede the last commit frame, so uncommitted appends are invisible
* BY CONSTRUCTION (not as an accident of buffering), no matter how
* large the append or what reached the page cache. A crash discards
* only the un-committed suffix: on the next open, bytes after the last
* commit frame are truncated and the LSN sequence continues from the
* last committed record — LSNs of truncated records are reused, but
* only ever for records no scan could have observed. A CRC failure
* BEFORE the last commit frame is damage to acknowledged data and
* fails ray_aof_open with RAY_ERR_CORRUPT rather than truncating.
* (The torn-tail tolerance is deliberate and differs from the
* transaction journal, where a torn tail is fatal: AOF payloads are
* opaque data the writer was never acknowledged for, not replayable
* commands.)
*
* Threading: one writer handle per directory, no internal locking.
* Concurrent ray_aof_scan() calls are safe, including against a live
* writer — a scan observes the committed prefix and stops cleanly at
* the first incomplete tail record.
*
* Errors: RAY_ERR_DOMAIN on bad arguments, RAY_ERR_IO on filesystem
* failure, RAY_ERR_LIMIT on payload >= 2^32-1 bytes, RAY_ERR_CORRUPT
* from open or scan when acknowledged (committed) data fails its CRC.
*/
typedef struct ray_aof_s ray_aof_t;
/* Open (creating the directory if needed) and recover the log at `dir`.
* `segment_limit` <= 0 selects RAY_AOF_DEFAULT_SEGMENT_LIMIT. On
* failure returns NULL and sets *out_err (out_err may be NULL). */
ray_aof_t* ;
/* Buffered append of `len` bytes; returns the reserved LSN (>= 0), or
* -1 with *out_err set. Durable only after ray_aof_commit(). */
int64_t ;
/* Durability barrier: flush + fsync the active segment. */
ray_err_t ;
/* The LSN the next append will receive. */
int64_t ;
/* Scan callback: return true to continue, false to stop the scan. */
typedef bool ;
/* Scan committed records with lsn >= from_lsn in LSN order, invoking
* `cb` per record. Needs no ray_aof_t handle — reads directly from
* `dir`, concurrently with a live writer. Returns the number of
* records delivered, or -1 with *out_err set. */
int64_t ;
/* Flush, fsync and close; frees the handle. Returns the commit error
* if the final flush fails (the handle is freed either way). */
ray_err_t ;
}
/* RAY_H */