| /// @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. | |
| extern "C" { | |
| // ββ 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); | |
| } | |