A thin layer over the C ABI. Every name follows c/usearch/: a C verb usearch_dense_<verb> is a <verb> here, in camelCase, and enums mirror C enums, never strings.
Every type is its C name without usearch_ and _t, a verb’s argument structure becomes its Dense*Config, and every wrapper’s documentation names the C symbol it calls or says it is binding-only.
The receiver chooses, the verb stays. The index runs a verb on the calling thread, on(executor) blocks on an executor, and deferred(executor, &call) submits it, all with the same arguments.
Deferred calls use the language’s own idioms.status polls through usearch_outcome_status, wait blocks through usearch_outcome_wait, and with no async left in Zig, waiting is how a result is collected.
No life of its own. The binding starts no threads and keeps no queues; releasing a Deferred rides defer call.deinit(), which waits for the call first.
Arenas are lent and reused, never shared. Every output whose length scales with the call lands in an arena the caller passes; each view carries the arena’s generation, and reads after the arena serves another call answer Error.Uninitialized.
Nothing costs anything until it is used. Submitting a call allocates nothing, and an arena allocates only when a call writes into it.
Layouts are declared, not translated. An extern struct already has the ABI’s layout and an enum(c_int) its width, so no call site casts what a translated header would hand back as c_uint or ?*anyopaque.
Callbacks are comptime functions. Predicates, progress handlers and value lookups wrap a function known at compile time, so the trampoline crossing the boundary is generated per call site and nothing is boxed.