Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions pj_base/include/pj_base/data_source_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,27 @@ typedef enum {
PJ_DATA_SOURCE_STATE_STOPPING = 5,
PJ_DATA_SOURCE_STATE_STOPPED = 6, /**< Terminal. */
PJ_DATA_SOURCE_STATE_FAILED = 7, /**< Terminal. */
/* Forces a stable 4-byte width across compilers, so a plugin built with
* -fshort-enums cannot shrink this enum and misalign by-value uses. Not a
* real state; never returned or accepted. */
PJ_DATA_SOURCE_STATE_FORCE_INT32 = 0x7FFFFFFF,
} PJ_data_source_state_t;

/** Severity level for plugin-to-host diagnostic messages. */
typedef enum {
PJ_DATA_SOURCE_MESSAGE_INFO = 0,
PJ_DATA_SOURCE_MESSAGE_WARNING = 1,
PJ_DATA_SOURCE_MESSAGE_ERROR = 2,
PJ_DATA_SOURCE_MESSAGE_FORCE_INT32 = 0x7FFFFFFF, /* pin 4-byte width; not a real level */
} PJ_data_source_message_level_t;

/** Type of message box to display. Determines the icon shown. */
typedef enum {
PJ_MESSAGE_BOX_INFO = 0, /**< Information icon (i). */
PJ_MESSAGE_BOX_WARNING = 1, /**< Warning icon (!). */
PJ_MESSAGE_BOX_ERROR = 2, /**< Error/critical icon (X). */
PJ_MESSAGE_BOX_QUESTION = 3, /**< Question icon (?). */
PJ_MESSAGE_BOX_INFO = 0, /**< Information icon (i). */
PJ_MESSAGE_BOX_WARNING = 1, /**< Warning icon (!). */
PJ_MESSAGE_BOX_ERROR = 2, /**< Error/critical icon (X). */
PJ_MESSAGE_BOX_QUESTION = 3, /**< Question icon (?). */
PJ_MESSAGE_BOX_TYPE_FORCE_INT32 = 0x7FFFFFFF, /* pin 4-byte width; not a real type */
} PJ_message_box_type_t;

/**
Expand All @@ -110,6 +116,7 @@ typedef enum {
PJ_MSG_BTN_ABORT = 0x20,
PJ_MSG_BTN_RETRY = 0x40,
PJ_MSG_BTN_IGNORE = 0x80,
PJ_MSG_BTN_FORCE_INT32 = 0x7FFFFFFF, /* pin 4-byte width; not a real button */
} PJ_message_box_buttons_t;

/**
Expand Down
47 changes: 26 additions & 21 deletions pj_base/include/pj_base/plugin_data_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,22 @@ typedef enum {
/** Sentinel: null value with no type information. Used when is_null=true
* and the plugin provides no type hint (untyped kNull). */
PJ_PRIMITIVE_TYPE_UNSPECIFIED = 0xFF,
/* Forces a stable 4-byte width across compilers, so a plugin built with
* -fshort-enums cannot shrink this enum and misalign the by-value uses in
* PJ_scalar_value_t / PJ_field_info_t / ensure_field. Not a real type. */
PJ_PRIMITIVE_TYPE_FORCE_INT32 = 0x7FFFFFFF,
} PJ_primitive_type_t;

/* ABI-FROZEN: layout permanent; changes = ABI break. */
typedef struct {
const char* data;
size_t size;
uint64_t size;
} PJ_string_view_t;

/* ABI-FROZEN: layout permanent; changes = ABI break. */
typedef struct {
const uint8_t* data;
size_t size;
uint64_t size;
} PJ_bytes_view_t;

/* ==========================================================================
Expand Down Expand Up @@ -317,11 +321,11 @@ typedef struct {

typedef struct {
const PJ_data_source_info_t* data_sources;
size_t data_source_count;
uint64_t data_source_count;
const PJ_topic_info_t* topics;
size_t topic_count;
uint64_t topic_count;
const PJ_field_info_t* fields;
size_t field_count;
uint64_t field_count;
void* release_ctx;
void (*release)(void* release_ctx);
} PJ_catalog_snapshot_t;
Expand Down Expand Up @@ -373,13 +377,13 @@ typedef struct PJ_source_write_host_vtable_t {
/* [stream-thread] Append a record by field name. Convenience path for
* simple plugins; resolves field handles on every call. */
bool (*append_record)(
void* ctx, PJ_topic_handle_t topic, int64_t timestamp, const PJ_named_field_value_t* fields, size_t field_count,
void* ctx, PJ_topic_handle_t topic, int64_t timestamp, const PJ_named_field_value_t* fields, uint64_t field_count,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [stream-thread] Append a record with pre-resolved field handles. Fast
* path for streaming producers — skip the name lookup. */
bool (*append_bound_record)(
void* ctx, PJ_topic_handle_t topic, int64_t timestamp, const PJ_bound_field_value_t* fields, size_t field_count,
void* ctx, PJ_topic_handle_t topic, int64_t timestamp, const PJ_bound_field_value_t* fields, uint64_t field_count,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [stream-thread] PRIMARY BATCH PATH. Plugin hands ownership of an Arrow
Expand Down Expand Up @@ -417,12 +421,12 @@ typedef struct PJ_parser_write_host_vtable_t {

/* [stream-thread] Append a record by field name. */
bool (*append_record)(
void* ctx, int64_t timestamp, const PJ_named_field_value_t* fields, size_t field_count,
void* ctx, int64_t timestamp, const PJ_named_field_value_t* fields, uint64_t field_count,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [stream-thread] Append a record with pre-resolved field handles. */
bool (*append_bound_record)(
void* ctx, int64_t timestamp, const PJ_bound_field_value_t* fields, size_t field_count,
void* ctx, int64_t timestamp, const PJ_bound_field_value_t* fields, uint64_t field_count,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [stream-thread] Optional batch path. Plugin hands ownership of an Arrow
Expand Down Expand Up @@ -474,12 +478,12 @@ typedef struct PJ_toolbox_host_vtable_t {

/* [main-thread] Append a record by field name. */
bool (*append_record)(
void* ctx, PJ_topic_handle_t topic, int64_t timestamp, const PJ_named_field_value_t* fields, size_t field_count,
void* ctx, PJ_topic_handle_t topic, int64_t timestamp, const PJ_named_field_value_t* fields, uint64_t field_count,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [main-thread] Append a record with pre-resolved field handles. */
bool (*append_bound_record)(
void* ctx, PJ_topic_handle_t topic, int64_t timestamp, const PJ_bound_field_value_t* fields, size_t field_count,
void* ctx, PJ_topic_handle_t topic, int64_t timestamp, const PJ_bound_field_value_t* fields, uint64_t field_count,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [main-thread] Bulk-write via Arrow C Data Interface (same ownership rule
Expand Down Expand Up @@ -516,7 +520,7 @@ typedef struct PJ_toolbox_host_vtable_t {
* push is not offered on the toolbox surface (plugin holds the bytes
* already by the time it calls). */
bool (*push_owned_object)(
void* ctx, PJ_object_topic_handle_t topic, int64_t timestamp_ns, const uint8_t* data, size_t size,
void* ctx, PJ_object_topic_handle_t topic, int64_t timestamp_ns, const uint8_t* data, uint64_t size,
PJ_error_t* out_error) PJ_NOEXCEPT;
} PJ_toolbox_host_vtable_t;

Expand Down Expand Up @@ -549,7 +553,7 @@ typedef struct {
* fetch context — valid at least until the NEXT call to the same fn or
* until fetch_ctx_destroy runs. The host immediately copies the bytes; the
* plugin may reuse or free the buffer on the following call. */
typedef bool (*PJ_lazy_fetch_fn_t)(void* fetch_ctx, const uint8_t** out_data, size_t* out_size) PJ_NOEXCEPT;
typedef bool (*PJ_lazy_fetch_fn_t)(void* fetch_ctx, const uint8_t** out_data, uint64_t* out_size) PJ_NOEXCEPT;

/* ABI-APPENDABLE: new slots may be added at the tail; struct_size gates read.
*
Expand Down Expand Up @@ -580,7 +584,7 @@ typedef struct PJ_object_write_host_vtable_t {
* (markers, annotations, scene primitives) whose aggregate volume stays
* comfortably in memory. */
bool (*push_owned)(
void* ctx, PJ_object_topic_handle_t topic, int64_t timestamp_ns, const uint8_t* data, size_t size,
void* ctx, PJ_object_topic_handle_t topic, int64_t timestamp_ns, const uint8_t* data, uint64_t size,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [stream-thread] Push a lazy entry — host stores the fetch closure, not
Expand All @@ -598,7 +602,7 @@ typedef struct PJ_object_write_host_vtable_t {
* Typical plugin author usage: do NOT call this. The application owns
* the retention policy; DataSource plugins should leave budgets alone. */
void (*set_retention_budget)(
void* ctx, PJ_object_topic_handle_t topic, int64_t time_window_ns, size_t max_memory_bytes) PJ_NOEXCEPT;
void* ctx, PJ_object_topic_handle_t topic, int64_t time_window_ns, uint64_t max_memory_bytes) PJ_NOEXCEPT;
} PJ_object_write_host_vtable_t;

/* ABI-FROZEN: fat pointer layout permanent. */
Expand Down Expand Up @@ -634,7 +638,7 @@ typedef struct PJ_parser_object_write_host_vtable_t {

/* [stream-thread] Eager push of serialized payload bytes into the bound
* object topic. Store copies the bytes. */
bool (*push_owned)(void* ctx, int64_t timestamp_ns, const uint8_t* data, size_t size, PJ_error_t* out_error)
bool (*push_owned)(void* ctx, int64_t timestamp_ns, const uint8_t* data, uint64_t size, PJ_error_t* out_error)
PJ_NOEXCEPT;

/* [stream-thread] Lazy push. Rarely used from parsers (a delegated parser
Expand Down Expand Up @@ -689,7 +693,7 @@ typedef struct PJ_object_read_host_vtable_t {
* up to that many handles and always sets *out_count to the TOTAL number
* of topics (so the caller can detect truncation and resize). */
bool (*list_topics)(
void* ctx, PJ_object_topic_handle_t* out_buffer, size_t buffer_capacity, size_t* out_count,
void* ctx, PJ_object_topic_handle_t* out_buffer, uint64_t buffer_capacity, uint64_t* out_count,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [main-thread] Return the topic's metadata JSON — a pointer stable for
Expand All @@ -706,13 +710,13 @@ typedef struct PJ_object_read_host_vtable_t {

/* [thread-safe] Expose the bytes behind an owning handle. View is valid
* until release_bytes(handle). Safe to call from decoder worker threads. */
void (*get_bytes)(PJ_object_bytes_handle_t handle, const uint8_t** out_data, size_t* out_size) PJ_NOEXCEPT;
void (*get_bytes)(PJ_object_bytes_handle_t handle, const uint8_t** out_data, uint64_t* out_size) PJ_NOEXCEPT;

/* [thread-safe] Release an owning handle. Idempotent on NULL. */
void (*release_bytes)(PJ_object_bytes_handle_t handle) PJ_NOEXCEPT;

/* [main-thread] Entry count for a topic. 0 on bad handle. */
size_t (*entry_count)(void* ctx, PJ_object_topic_handle_t topic) PJ_NOEXCEPT;
uint64_t (*entry_count)(void* ctx, PJ_object_topic_handle_t topic) PJ_NOEXCEPT;

/* [main-thread] Time range [min, max] for a topic. Returns false if the
* topic is unknown or empty. */
Expand Down Expand Up @@ -775,12 +779,13 @@ typedef struct PJ_settings_store_vtable_t {
/* [main-thread] Read a string list. On found, *out_items points to an array
* of *out_count entries, valid until the next call on this store. */
bool (*get_string_list)(
void* ctx, PJ_string_view_t key, const PJ_string_view_t** out_items, size_t* out_count, bool* out_found,
void* ctx, PJ_string_view_t key, const PJ_string_view_t** out_items, uint64_t* out_count, bool* out_found,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [main-thread] Write a string list (create or overwrite). */
bool (*set_string_list)(
void* ctx, PJ_string_view_t key, const PJ_string_view_t* items, size_t count, PJ_error_t* out_error) PJ_NOEXCEPT;
void* ctx, PJ_string_view_t key, const PJ_string_view_t* items, uint64_t count,
PJ_error_t* out_error) PJ_NOEXCEPT;

/* [main-thread] Report whether a key exists, in *out_present. */
bool (*contains)(void* ctx, PJ_string_view_t key, bool* out_present, PJ_error_t* out_error) PJ_NOEXCEPT;
Expand Down
2 changes: 1 addition & 1 deletion pj_base/include/pj_base/sdk/object_bytes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ObjectBytes {
return {};
}
const uint8_t* data = nullptr;
std::size_t size = 0;
uint64_t size = 0; // matches PJ_object_read_host_vtable_t::get_bytes (uint64_t*)
vtable_->get_bytes(handle_, &data, &size);
return Span<const uint8_t>(data, size);
}
Expand Down
12 changes: 6 additions & 6 deletions pj_base/include/pj_base/sdk/plugin_data_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ class ToolboxObjectReadHostView {
return unexpected("toolbox object read host is not bound");
}
// First pass: ask for the count.
std::size_t count = 0;
uint64_t count = 0; // matches PJ_object_read_host_vtable_t::list_topics (uint64_t*)
PJ_error_t err{};
if (!host_.vtable->list_topics(host_.ctx, nullptr, 0, &count, &err)) {
return unexpected(errorToString(err));
Expand Down Expand Up @@ -655,7 +655,7 @@ class ToolboxObjectReadHostView {
return ObjectBytes(handle, host_.vtable);
}

[[nodiscard]] std::size_t entryCount(ObjectTopicHandle topic) const {
[[nodiscard]] uint64_t entryCount(ObjectTopicHandle topic) const {
if (!valid() || host_.vtable->entry_count == nullptr) {
return 0;
}
Expand Down Expand Up @@ -764,7 +764,7 @@ class SourceObjectWriteHostView {
}

/// Configure retention. Application-level concern — plugins rarely call this.
void setRetentionBudget(ObjectTopicHandle topic, int64_t time_window_ns, size_t max_memory_bytes) const {
void setRetentionBudget(ObjectTopicHandle topic, int64_t time_window_ns, uint64_t max_memory_bytes) const {
if (!valid()) {
return;
}
Expand All @@ -786,7 +786,7 @@ class SourceObjectWriteHostView {
FetchFn fetch;
std::vector<uint8_t> last_bytes;

static bool trampoline(void* ctx, const uint8_t** out_data, size_t* out_size) noexcept {
static bool trampoline(void* ctx, const uint8_t** out_data, uint64_t* out_size) noexcept {
if (ctx == nullptr || out_data == nullptr || out_size == nullptr) {
return false;
}
Expand Down Expand Up @@ -866,7 +866,7 @@ class ParserObjectWriteHostView {
FetchFn fetch;
std::vector<uint8_t> last_bytes;

static bool trampoline(void* ctx, const uint8_t** out_data, size_t* out_size) noexcept {
static bool trampoline(void* ctx, const uint8_t** out_data, uint64_t* out_size) noexcept {
if (ctx == nullptr || out_data == nullptr || out_size == nullptr) {
return false;
}
Expand Down Expand Up @@ -1442,7 +1442,7 @@ class SettingsView {
return result;
}
const PJ_string_view_t* items = nullptr;
std::size_t count = 0;
uint64_t count = 0; // matches PJ_settings_store_vtable_t::get_string_list (uint64_t*)
bool found = false;
PJ_error_t err{};
if (!store_.vtable->get_string_list(store_.ctx, toAbiString(key), &items, &count, &found, &err)) {
Expand Down
4 changes: 2 additions & 2 deletions pj_base/include/pj_base/sdk/settings_store_host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class SettingsStoreHost {
}

static bool tGetStringList(
void* ctx, PJ_string_view_t key, const PJ_string_view_t** out_items, size_t* out_count, bool* out_found,
void* ctx, PJ_string_view_t key, const PJ_string_view_t** out_items, uint64_t* out_count, bool* out_found,
PJ_error_t* out_error) noexcept {
if (ctx == nullptr || out_items == nullptr || out_count == nullptr || out_found == nullptr) {
fillError(out_error, 2, "settings", "null ctx or out-param");
Expand Down Expand Up @@ -140,7 +140,7 @@ class SettingsStoreHost {
}

static bool tSetStringList(
void* ctx, PJ_string_view_t key, const PJ_string_view_t* items, size_t count, PJ_error_t* out_error) noexcept {
void* ctx, PJ_string_view_t key, const PJ_string_view_t* items, uint64_t count, PJ_error_t* out_error) noexcept {
if (ctx == nullptr || (items == nullptr && count != 0)) {
fillError(out_error, 2, "settings", "null ctx or items");
return false;
Expand Down
4 changes: 2 additions & 2 deletions pj_base/include/pj_base/sdk/testing/parser_write_recorder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class ParserWriteRecorder {
}

static bool trampolineAppendRecord(
void* ctx, int64_t timestamp, const PJ_named_field_value_t* fields, size_t field_count, PJ_error_t*) noexcept {
void* ctx, int64_t timestamp, const PJ_named_field_value_t* fields, uint64_t field_count, PJ_error_t*) noexcept {
auto* self = static_cast<ParserWriteRecorder*>(ctx);
RecordedRow row;
row.timestamp = timestamp;
Expand All @@ -198,7 +198,7 @@ class ParserWriteRecorder {
}

static bool trampolineAppendBoundRecord(
void* ctx, int64_t timestamp, const PJ_bound_field_value_t* fields, size_t field_count, PJ_error_t*) noexcept {
void* ctx, int64_t timestamp, const PJ_bound_field_value_t* fields, uint64_t field_count, PJ_error_t*) noexcept {
auto* self = static_cast<ParserWriteRecorder*>(ctx);
RecordedRow row;
row.timestamp = timestamp;
Expand Down
1 change: 1 addition & 0 deletions pj_base/include/pj_base/toolbox_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ typedef enum {
PJ_TOOLBOX_MESSAGE_INFO = 0,
PJ_TOOLBOX_MESSAGE_WARNING = 1,
PJ_TOOLBOX_MESSAGE_ERROR = 2,
PJ_TOOLBOX_MESSAGE_FORCE_INT32 = 0x7FFFFFFF, /* pin 4-byte width; not a real level */
} PJ_toolbox_message_level_t;

enum {
Expand Down
7 changes: 5 additions & 2 deletions pj_base/tests/abi_layout_sentinels_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,15 @@
static_assert(sizeof(void*) == 8, "v4 ABI pinned to 64-bit targets");

// --- Enum size guards --------------------------------------------------------
// Defends against `-fshort-enums` and similar flags that silently shrink
// enums below the 32-bit wire assumption.
// Each ABI enum carries a `..._FORCE_INT32 = 0x7FFFFFFF` enumerator that pins
// its width to a stable 4 bytes even under `-fshort-enums` in a third-party
// plugin build — the enumerator is what travels into the plugin's compiler;
// these static_asserts only verify the pinning holds in this build too.
static_assert(sizeof(PJ_primitive_type_t) == 4, "enum layout pinned");
static_assert(sizeof(PJ_data_source_state_t) == 4, "enum layout pinned");
static_assert(sizeof(PJ_data_source_message_level_t) == 4, "enum layout pinned");
static_assert(sizeof(PJ_message_box_type_t) == 4, "enum layout pinned");
static_assert(sizeof(PJ_message_box_buttons_t) == 4, "enum layout pinned");
static_assert(sizeof(PJ_toolbox_message_level_t) == 4, "enum layout pinned");

// --- PJ_error_t (ABI-FROZEN) -------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions pj_base/tests/plugin_data_api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ bool parserEnsureField(
return true;
}

bool parserAppendRecord(void*, int64_t, const PJ_named_field_value_t*, std::size_t, PJ_error_t*) noexcept {
bool parserAppendRecord(void*, int64_t, const PJ_named_field_value_t*, uint64_t, PJ_error_t*) noexcept {
return true;
}

bool parserAppendBoundRecord(void* ctx, int64_t, const PJ_bound_field_value_t*, std::size_t, PJ_error_t*) noexcept {
bool parserAppendBoundRecord(void* ctx, int64_t, const PJ_bound_field_value_t*, uint64_t, PJ_error_t*) noexcept {
static_cast<TailSlotRecorder*>(ctx)->called = true;
return true;
}
Expand Down
Loading
Loading