Skip to main content

rayforce_sys/
lib.rs

1//! Raw FFI bindings to the RayforceDB v2 core (`librayforce`).
2//!
3//! Generated by `bindgen` from the core's own headers: the public
4//! `rayforce.h`, plus the private ones declaring the handful of internal
5//! symbols the safe crate needs (`INTERNAL_FNS` in `build.rs` is the full
6//! list). This crate is `unsafe` and 1:1 with the C ABI; use the safe
7//! `rayforce` crate instead.
8//!
9//! The header's function-like macros (`ray_type`, `ray_len`, `ray_data`,
10//! `RAY_IS_ERR`, `RAY_IS_NULL`, …) are not emitted by bindgen — the safe crate
11//! reimplements them in Rust against the generated [`ray_t`] layout.
12#![allow(non_upper_case_globals)]
13#![allow(non_camel_case_types)]
14#![allow(non_snake_case)]
15#![allow(dead_code)]
16#![allow(clippy::all)]
17
18include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
19
20// Q IPC wire-format client from the shared `rayforce-q` repo (q.c/q.h). Not
21// part of the engine bindings; hand-declared here to match `q.h`.
22extern "C" {
23    /// Open a TCP connection to a Q server and perform the login handshake.
24    /// Returns a connection fd (>= 0), or a negative `Q_ERR_*` code.
25    pub fn q_connect(
26        host: *const ::std::os::raw::c_char,
27        port: ::std::os::raw::c_int,
28        user: *const ::std::os::raw::c_char,
29        password: *const ::std::os::raw::c_char,
30        timeout_ms: ::std::os::raw::c_int,
31    ) -> ::std::os::raw::c_int;
32    /// Close a connection fd. Returns 0 on success, -1 on an invalid fd.
33    pub fn q_close(fd: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
34    /// Encode + exchange + decode: send `msg` and return the decoded response
35    /// (possibly a `RAY_ERROR`), or null on a transport/serialization failure
36    /// with a short reason written to `err`.
37    pub fn q_send(
38        fd: ::std::os::raw::c_int,
39        msg: *mut ray_t,
40        err: *mut ::std::os::raw::c_char,
41        errlen: usize,
42    ) -> *mut ray_t;
43    /// Decompress (if needed) and deserialize a response *body* (wire header
44    /// already stripped) into a freshly-owned object — possibly a `RAY_ERROR`
45    /// carrying a Q server-side error. Touches the symbol table: engine thread
46    /// only. Returns null on a decode failure with a short reason in `err`.
47    pub fn q_decode(
48        resp: *mut u8,
49        resp_len: i64,
50        compressed: ::std::os::raw::c_int,
51        err: *mut ::std::os::raw::c_char,
52        errlen: usize,
53    ) -> *mut ray_t;
54    /// As [`q_decode`], but a table comes back with only the `ncols` columns
55    /// named in `cols`, in the order named (q's `cols#t`). The other columns
56    /// are skipped by their serialized length: nothing is allocated or
57    /// interned for them, and a column `q_decode` rejects (a timespan) can be
58    /// skipped. For a keyed table the key comes back whole and the names pick
59    /// among the value columns. A name the table lacks is a `RAY_ERROR` naming
60    /// it; a null or repeated name returns null with `err` set. With
61    /// `ncols == 0`, or a message that is not a table, this is `q_decode`.
62    /// Since rayforce-q 2.5.0. Engine thread only.
63    pub fn q_decode_cols(
64        resp: *mut u8,
65        resp_len: i64,
66        compressed: ::std::os::raw::c_int,
67        cols: *const *const ::std::os::raw::c_char,
68        ncols: ::std::os::raw::c_int,
69        err: *mut ::std::os::raw::c_char,
70        errlen: usize,
71    ) -> *mut ray_t;
72    /// Serialize `msg` into a complete Q wire request (8-byte header + body).
73    /// The buffer is malloc'd by C and must be released with `libc::free`.
74    /// `q_encode` always stamps the header's message-type byte as SYNC; a
75    /// publisher retypes `req[1]` in place to send ASYNC or RESPONSE.
76    /// Touches the symbol table: engine thread only.
77    pub fn q_encode(
78        msg: *mut ray_t,
79        req: *mut *mut u8,
80        req_len: *mut i64,
81        err: *mut ::std::os::raw::c_char,
82        errlen: usize,
83    ) -> ::std::os::raw::c_int;
84    /// Send a pre-encoded request on `fd` and read the raw response *body*.
85    /// Pure socket I/O — the half of `q_send` that a runtime with a global lock
86    /// can perform with that lock released.
87    pub fn q_exchange(
88        fd: ::std::os::raw::c_int,
89        req: *const u8,
90        req_len: i64,
91        resp: *mut *mut u8,
92        resp_len: *mut i64,
93        compressed: *mut ::std::os::raw::c_int,
94        err: *mut ::std::os::raw::c_char,
95        errlen: usize,
96    ) -> ::std::os::raw::c_int;
97}
98
99// Q wire-format *server* from `rayforce-q` (q_server.c/q_server.h), available
100// since rayforce-q 2.1.0. Where the client above lets you call a Q server, this
101// lets you receive from one.
102//
103// `q_send` is request/response over a blocking socket, so a frame the peer
104// pushes unsolicited would be read as the answer to the next call — which makes
105// a subscription impossible with the client alone. Attaching the fd to a
106// rayforce poll fixes that: the event loop owns the reads and routes each frame
107// by message type, waking a parked `q_conn_send` on a RESPONSE and dispatching
108// anything else to the function the publisher named.
109extern "C" {
110    /// Register a Q-protocol *listener* on `poll`, bound to TCP `port`.
111    /// Returns the poll selector id (>= 0), or -1 on failure.
112    pub fn q_serve(poll: *mut ray_poll_t, port: ::std::os::raw::c_int) -> i64;
113    /// Put an already-connected, already-handshaken `q_connect` fd under
114    /// `poll`'s rx machine. Returns a poll selector id (>= 0) — the handle for
115    /// the two calls below — or -1. **The fd is owned by the poll from here on;
116    /// do not `q_close` it.**
117    pub fn q_conn_attach(poll: *mut ray_poll_t, fd: ::std::os::raw::c_int) -> i64;
118    /// Sync round-trip on an attached connection: write a SYNC frame, then pump
119    /// this connection until its RESPONSE arrives — dispatching, not swallowing,
120    /// any frame that arrives in between. So a bound handler can fire before
121    /// this returns. Returns a freshly-owned object, possibly a `RAY_ERROR`.
122    /// Refuses a nested call from inside a handler.
123    pub fn q_conn_send(poll: *mut ray_poll_t, id: i64, msg: *mut ray_t) -> *mut ray_t;
124    /// Close an attached connection and release its state. Illegal once the rx
125    /// machine has already deregistered the selector — check `ray_poll_get`.
126    pub fn q_conn_close(poll: *mut ray_poll_t, id: i64);
127}
128
129/// `q_connect` failure codes (mirrors `q.h`).
130pub const Q_ERR_SOCKET: ::std::os::raw::c_int = -1;
131pub const Q_ERR_HANDSHAKE: ::std::os::raw::c_int = -2;
132pub const Q_ERR_TIMEOUT: ::std::os::raw::c_int = -3;
133
134/// `ray_ipc_connect` failure codes.
135///
136/// The public header declares the function with no contract at all
137/// (`include/rayforce.h`); this mirrors the comment on the private
138/// `src/core/ipc.h` declaration and, for [`RAY_IPC_ERR_OS`], the
139/// `connect_fail_code()` classifier in `src/core/ipc.c` that the header's
140/// comment predates. Hand-maintained against a core bump, like `Q_ERR_*`.
141///
142/// [`RAY_IPC_ERR_REFUSED`] is the documented name for -1, but the core also
143/// returns it for a missing poll, a credential buffer overflow and a failed
144/// poll registration — treat it as the catch-all it is.
145pub const RAY_IPC_ERR_REFUSED: i64 = -1;
146/// The server demands credentials and the caller supplied no password.
147pub const RAY_IPC_ERR_AUTH_REQUIRED: i64 = -2;
148/// The server rejected the credentials.
149pub const RAY_IPC_ERR_AUTH_FAILED: i64 = -3;
150/// The peer speaks a different serialization wire version.
151pub const RAY_IPC_ERR_WIRE_VERSION: i64 = -4;
152/// No answer within the connect/handshake budget. The core folds `EAGAIN` and
153/// `EWOULDBLOCK` in here too, so this also covers a live server that is busy
154/// inside a long evaluation.
155pub const RAY_IPC_ERR_TIMEOUT: i64 = -5;
156/// Some other OS error; the core leaves `errno` holding it.
157pub const RAY_IPC_ERR_OS: i64 = -6;
158
159/// Function attribute flags for `ray_fn_unary` / `ray_fn_vary`, from the core's
160/// `src/lang/eval.h:33-40`. They are `#define`s in a header `wrapper.h` does
161/// not include, so bindgen never sees them.
162///
163/// `RAY_FN_NONE` is what a plain callback wants: no auto-mapping over vectors,
164/// no aggregation, args evaluated normally.
165pub const RAY_FN_NONE: u8 = 0x00;
166pub const RAY_FN_LEFT_ATOMIC: u8 = 0x01;
167pub const RAY_FN_RIGHT_ATOMIC: u8 = 0x02;
168pub const RAY_FN_ATOMIC: u8 = 0x04;
169pub const RAY_FN_AGGR: u8 = 0x08;
170pub const RAY_FN_SPECIAL_FORM: u8 = 0x10;
171pub const RAY_FN_RESTRICTED: u8 = 0x20;
172pub const RAY_FN_LAZY_AWARE: u8 = 0x80;