File size: 10,285 Bytes
3374e90 | 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 | #pragma once
/// @file bex_engine.h
/// @brief Pure C ABI for the Bex WASM Plugin Engine (v4).
///
/// This header defines the boundary between the Rust engine and any C/C++ consumer.
/// Rust implements these functions via `extern "C"`. C++ consumes them directly.
/// No bridge crate, no code generation β just link against libbex_runtime.
///
/// Architecture:
/// - All async operations return a request_id immediately.
/// - When the operation completes, Rust invokes the BexResultCallback from a
/// background Tokio thread.
/// - C++ must copy/parse the payload before the callback returns (payload is
/// owned by Rust and freed after the callback returns).
/// - Sync operations (install, uninstall, list, secrets) block until done.
///
/// Thread safety:
/// - bex_engine_new / bex_engine_free are NOT thread-safe.
/// - All bex_submit_* functions are thread-safe (internally synchronized).
/// - The callback is invoked from a Rust/Tokio background thread β the
/// callback implementation must be thread-safe.
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
// ββ Opaque Engine Handle βββββββββββββββββββββββββββββββββββββββββββββββ
/// Opaque handle to the Rust BexEngine runtime.
typedef struct BexEngine BexEngine;
// ββ Callback Signature βββββββββββββββββββββββββββββββββββββββββββββββββ
/// Universal async result callback.
///
/// Rust calls this from a background Tokio thread when an async task finishes.
///
/// @param user_data The opaque pointer passed to the submit function.
/// @param request_id The ID returned by the submit function.
/// @param success true if the operation succeeded, false on error.
/// @param payload Pointer to the result payload bytes (JSON string).
/// Owned by Rust β C++ must copy before returning.
/// @param payload_len Number of bytes in payload.
typedef void (*BexResultCallback)(
void* user_data,
uint64_t request_id,
bool success,
const uint8_t* payload,
size_t payload_len
);
// ββ Plugin Info (returned by list/info sync calls) βββββββββββββββββββββ
/// Information about a single installed plugin.
/// Returned by bex_engine_list_plugins and bex_engine_plugin_info.
typedef struct BexPluginInfo {
char* id; ///< Plugin identifier (e.g., "com.gogoanime")
char* name; ///< Human-readable plugin name
char* version; ///< Plugin version string
uint32_t capabilities; ///< Capability bitmask
bool enabled; ///< Whether the plugin is currently enabled
char* description; ///< Plugin description (may be empty)
char* author; ///< Plugin author (may be empty)
char* homepage; ///< Plugin homepage URL (may be empty)
} BexPluginInfo;
/// Array of BexPluginInfo structs returned by bex_engine_list_plugins.
typedef struct BexPluginInfoList {
BexPluginInfo* items; ///< Array of plugin info structs
size_t count; ///< Number of items in the array
} BexPluginInfoList;
// ββ Lifecycle ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
/// Create a new BexEngine instance.
///
/// @param data_dir Path to the data directory (created if not exists).
/// @return Opaque engine handle, or NULL on failure.
BexEngine* bex_engine_new(const char* data_dir);
/// Free a BexEngine instance and release all resources.
///
/// This will wait for in-flight requests to complete (up to 10 seconds),
/// then shut down the Tokio runtime and release all memory.
///
/// @param engine The engine handle (may be NULL, in which case this is a no-op).
void bex_engine_free(BexEngine* engine);
// ββ Plugin Management (synchronous) ββββββββββββββββββββββββββββββββββββ
/// Install a plugin from a .bex package file.
///
/// @param engine The engine handle.
/// @param path Filesystem path to the .bex package.
/// @return 0 on success, non-zero on error.
int bex_engine_install(BexEngine* engine, const char* path);
/// Uninstall a plugin by its ID.
///
/// @param engine The engine handle.
/// @param id The plugin identifier.
/// @return 0 on success, non-zero on error.
int bex_engine_uninstall(BexEngine* engine, const char* id);
/// List all installed plugins.
///
/// Returns a BexPluginInfoList. The caller must free it with
/// bex_plugin_info_list_free when done.
///
/// @param engine The engine handle.
/// @return List of installed plugins (empty list if none, never NULL).
BexPluginInfoList bex_engine_list_plugins(BexEngine* engine);
/// Get detailed info for a single plugin.
///
/// @param engine The engine handle.
/// @param id The plugin identifier.
/// @param out Pointer to a BexPluginInfo struct to fill.
/// @return 0 on success, non-zero if plugin not found.
int bex_engine_plugin_info(BexEngine* engine, const char* id, BexPluginInfo* out);
/// Enable a plugin.
int bex_engine_enable(BexEngine* engine, const char* id);
/// Disable a plugin.
int bex_engine_disable(BexEngine* engine, const char* id);
/// Free a BexPluginInfoList returned by bex_engine_list_plugins.
void bex_plugin_info_list_free(BexPluginInfoList list);
/// Free the strings inside a BexPluginInfo struct.
void bex_plugin_info_free(BexPluginInfo info);
// ββ API Key / Secret Management (synchronous) βββββββββββββββββββββββββ
/// Set an API key/secret for a plugin.
///
/// @param engine The engine handle.
/// @param plugin_id The plugin identifier.
/// @param key The key name (e.g., "api_key").
/// @param value The key value.
/// @return 0 on success, non-zero on error.
int bex_engine_secret_set(BexEngine* engine, const char* plugin_id,
const char* key, const char* value);
/// Get an API key/secret value for a plugin.
///
/// @param engine The engine handle.
/// @param plugin_id The plugin identifier.
/// @param key The key name.
/// @param out_buf Buffer to write the value into.
/// @param out_buf_len Size of out_buf. On success, the actual length (excluding NUL) is written back.
/// @return 0 on success, non-zero if not found or error.
int bex_engine_secret_get(BexEngine* engine, const char* plugin_id,
const char* key, char* out_buf, size_t* out_buf_len);
/// Delete an API key/secret for a plugin.
///
/// @return 0 if deleted, 1 if key not found, negative on error.
int bex_engine_secret_delete(BexEngine* engine, const char* plugin_id,
const char* key);
/// List all secret key names for a plugin.
///
/// Returns a comma-separated string of key names. Caller must free with bex_string_free().
/// Returns NULL on error.
char* bex_engine_secret_keys(BexEngine* engine, const char* plugin_id);
/// Free a string returned by the engine (e.g., from bex_engine_secret_keys).
void bex_string_free(char* s);
// ββ Async Operations ββββββββββββββββββββββββββββββββββββββββββββββββββ
/// Submit a search request.
///
/// @param engine The engine handle.
/// @param plugin_id The plugin to use.
/// @param query The search query.
/// @param callback Called when the result is ready.
/// @param user_data Opaque pointer passed to the callback.
/// @return Request ID (non-zero). Returns 0 if engine is NULL or invalid.
uint64_t bex_submit_search(BexEngine* engine, const char* plugin_id,
const char* query,
BexResultCallback callback, void* user_data);
/// Submit a home page request.
uint64_t bex_submit_home(BexEngine* engine, const char* plugin_id,
BexResultCallback callback, void* user_data);
/// Submit a get_info request.
///
/// The media_id is opaque to the engine β the plugin knows how to interpret it.
uint64_t bex_submit_info(BexEngine* engine, const char* plugin_id,
const char* media_id,
BexResultCallback callback, void* user_data);
/// Submit a get_servers request.
///
/// The id is self-describing β the plugin knows how to parse its own IDs.
/// Example: "one-piece$ep=1$sub=1$dub=0"
uint64_t bex_submit_servers(BexEngine* engine, const char* plugin_id,
const char* id,
BexResultCallback callback, void* user_data);
/// Submit a resolve_stream request.
///
/// @param server_json JSON string representing a server entry (from get_servers result).
uint64_t bex_submit_stream(BexEngine* engine, const char* plugin_id,
const char* server_json,
BexResultCallback callback, void* user_data);
// ββ Cancellation ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
/// Cancel a pending async request.
///
/// @return true if the request was found and cancelled, false otherwise.
bool bex_cancel_request(BexEngine* engine, uint64_t request_id);
// ββ Engine Stats (synchronous) ββββββββββββββββββββββββββββββββββββββββ
/// Get engine statistics as a JSON string.
/// Caller must free the returned string with bex_string_free().
char* bex_engine_stats(BexEngine* engine);
// ββ Last Error ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
/// Get the last error message from a failed sync operation.
/// Returns NULL if no error. Caller must free with bex_string_free().
char* bex_engine_last_error(BexEngine* engine);
#ifdef __cplusplus
}
#endif
|