nim-sds/library/libsds.h
Ivan FB 05595e2d92
feat(ffi): target nim-ffi master (v0.2.0) — CBOR + event registry
Port the {.ffi.} wrapper to nim-ffi 0.2.0 (master). 0.2.0 is a breaking
redesign over 0.1.4: events move to a per-context multi-listener registry
(sds_add_event_listener / sds_remove_event_listener) fired via {.ffiEvent.}
emitters, and request/response/event marshalling switches from JSON to CBOR.

- libsds.nim: typed {.ffiEvent.} payloads replace the JSON event modules;
  CBOR handles nesting, so unwrap returns a typed response again. The
  retrieval-hint provider (a C function pointer, not CBOR-encodable) passes
  its address as a uint64 via a {.ffi.} method that stores it in a
  worker-thread threadvar.
- pin nim-ffi to master HEAD by commit. The lock version is kept a clean
  semver ("0.2.0") on purpose: nimble's `#`-prefixed special version in the
  lock breaks `nimble setup -l` (an unquoted `#` truncates the git path),
  so only vcsRevision carries the commit.
- add the new transitive dep cbor_serialization to the lock and nix/deps.nix.
- regenerate libsds.h for the CBOR/registry ABI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 13:22:11 +02:00

92 lines
4.1 KiB
C

// C API for libsds, built on the nim-ffi framework (v0.2.0+).
//
// Requests, responses and events are marshalled as CBOR. Request payloads are
// passed as a (reqCbor, reqCborLen) byte buffer; results and events are
// delivered to the callback as a CBOR buffer (msg, len). Each request/response
// struct and event payload is defined in library/libsds.nim. Events are
// wrapped in a CBOR envelope { eventType: <wire name>, payload: <struct> }.
#ifndef __libsds__
#define __libsds__
#include <stddef.h>
#include <stdint.h>
// The possible returned values for the functions that return int
#define RET_OK 0
#define RET_ERR 1
#define RET_MISSING_CALLBACK 2
#ifdef __cplusplus
extern "C" {
#endif
// Result/event callback. `msg` is the CBOR payload of length `len`.
// callerRet is one of the RET_* codes above.
typedef void (*SdsCallBack) (int callerRet, const char* msg, size_t len, void* userData);
// Synchronous provider invoked by SDS-R to fetch a retrieval hint for a
// message id. The implementation allocates `*hint` (and sets `*hintLen`); the
// library takes ownership and frees it with deallocShared. Registered via
// sds_set_retrieval_hint_provider (see below).
typedef void (*SdsRetrievalHintProvider) (const char* messageId, char** hint, size_t* hintLen, void* userData);
// --- Lifecycle -------------------------------------------------------------
// Create a context + ReliabilityManager. reqCbor encodes SdsConfig
// { participantId: tstr } (empty participantId disables SDS-R). Returns the
// context handle, or NULL on failure; the callback also fires on completion.
void* sds_create(const uint8_t* reqCbor, size_t reqCborLen, SdsCallBack callback, void* userData);
// Tear down the context created by sds_create. Blocks until the worker and
// watchdog threads have joined.
int sds_destroy(void* ctx);
// --- Events ----------------------------------------------------------------
// Subscribe `callback` to an event by wire name and receive a stable listener
// id (non-zero). Event wire names: "message_ready", "message_sent",
// "missing_dependencies", "periodic_sync", "repair_ready". Subscribe to each
// event separately. Payloads arrive as CBOR { eventType, payload }.
uint64_t sds_add_event_listener(void* ctx, const char* eventName, SdsCallBack callback, void* userData);
// Remove a listener by id. Returns 0 on success, non-zero if not found.
int sds_remove_event_listener(void* ctx, uint64_t listenerId);
// Register the SDS-R retrieval-hint provider. reqCbor encodes
// SdsHintProviderRequest { callbackAddr: uint, userDataAddr: uint } — the
// SdsRetrievalHintProvider function pointer and its user-data as integer
// addresses.
int sds_set_retrieval_hint_provider(void* ctx, SdsCallBack callback, void* userData, const uint8_t* reqCbor, size_t reqCborLen);
// --- Core API Functions ----------------------------------------------------
// Each takes a CBOR-encoded request buffer; the result is delivered to
// `callback` as CBOR.
// reqCbor: SdsWrapRequest { message: bytes, messageId: tstr, channelId: tstr }
// result: SdsWrapResponse { message: bytes }
int sds_wrap_outgoing_message(void* ctx, SdsCallBack callback, void* userData, const uint8_t* reqCbor, size_t reqCborLen);
// reqCbor: SdsUnwrapRequest { message: bytes }
// result: SdsUnwrapResponse { message: bytes, channelId: tstr,
// missingDeps: [{ messageId: tstr, retrievalHint: bytes }] }
int sds_unwrap_received_message(void* ctx, SdsCallBack callback, void* userData, const uint8_t* reqCbor, size_t reqCborLen);
// reqCbor: SdsMarkDependenciesRequest { messageIds: [tstr], channelId: tstr }
int sds_mark_dependencies_met(void* ctx, SdsCallBack callback, void* userData, const uint8_t* reqCbor, size_t reqCborLen);
// reqCbor: empty/unit payload (no fields).
int sds_reset(void* ctx, SdsCallBack callback, void* userData, const uint8_t* reqCbor, size_t reqCborLen);
// reqCbor: empty/unit payload (no fields).
int sds_start_periodic_tasks(void* ctx, SdsCallBack callback, void* userData, const uint8_t* reqCbor, size_t reqCborLen);
#ifdef __cplusplus
}
#endif
#endif /* __libsds__ */