/// Event kinds for the BEX async callback system. /// /// Each kind corresponds to a specific result type from the plugin API. /// The C++ backend uses these to dispatch events to the appropriate UI handler. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum BexEventKind { InstallResult, UninstallResult, HomeResult, CategoryResult, SearchResult, InfoResult, ServersResult, StreamResult, SubtitleSearchResult, SubtitleDownloadResult, ArticleResult, Log, Progress, Error, Cancelled, } impl BexEventKind { /// Convert to the integer tag used in the C ABI callback. /// Must stay in sync with the C++ side enum. pub fn to_tag(self) -> u8 { match self { Self::InstallResult => 0, Self::UninstallResult => 1, Self::HomeResult => 2, Self::CategoryResult => 3, Self::SearchResult => 4, Self::InfoResult => 5, Self::ServersResult => 6, Self::StreamResult => 7, Self::SubtitleSearchResult => 8, Self::SubtitleDownloadResult => 9, Self::ArticleResult => 10, Self::Log => 11, Self::Progress => 12, Self::Error => 13, Self::Cancelled => 14, } } } /// Payload format indicator. /// /// Tells the C++ consumer how to interpret the payload bytes. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum BexPayloadFormat { /// No payload (e.g., for Log/Progress events that carry data in fields). None, /// FlatBuffer binary — zero-copy deserialization on C++ side. FlatBuffer, /// JSON string — used for debug/CLI mode. JsonDebug, /// Opaque binary blob. Binary, } /// Internal event representation. /// /// Produced by the runtime for each completed request. The C++ backend /// drains these via `bex_drain_events()` and dispatches them to the UI. #[derive(Debug, Clone)] pub struct BexEvent { /// Monotonically increasing request ID (matches the ID returned by submit_*) pub request_id: u64, /// Monotonically increasing sequence number for ordering pub seq: u64, /// What kind of result this event carries pub kind: BexEventKind, /// Whether the operation succeeded pub ok: bool, /// Which plugin produced this event pub plugin_id: String, /// How to interpret the payload bytes pub payload_format: BexPayloadFormat, /// The actual result payload (FlatBuffer, JSON, or binary) pub payload: Vec, /// Machine-readable error code (empty if ok) pub error_code: String, /// Human-readable error message (empty if ok) pub error_message: String, } impl BexEvent { /// Create a success event with a FlatBuffer payload. pub fn success( request_id: u64, seq: u64, kind: BexEventKind, plugin_id: String, payload: Vec, ) -> Self { Self { request_id, seq, kind, ok: true, plugin_id, payload_format: BexPayloadFormat::FlatBuffer, payload, error_code: String::new(), error_message: String::new(), } } /// Create a success event with a JSON payload (for debug/CLI). pub fn success_json( request_id: u64, seq: u64, kind: BexEventKind, plugin_id: String, json: String, ) -> Self { Self { request_id, seq, kind, ok: true, plugin_id, payload_format: BexPayloadFormat::JsonDebug, payload: json.into_bytes(), error_code: String::new(), error_message: String::new(), } } /// Create an error event. pub fn error( request_id: u64, seq: u64, kind: BexEventKind, plugin_id: String, error_code: &str, error_message: &str, ) -> Self { Self { request_id, seq, kind, ok: false, plugin_id, payload_format: BexPayloadFormat::None, payload: Vec::new(), error_code: error_code.to_string(), error_message: error_message.to_string(), } } /// Create a cancellation event. pub fn cancelled(request_id: u64, seq: u64, plugin_id: String) -> Self { Self { request_id, seq, kind: BexEventKind::Cancelled, ok: false, plugin_id, payload_format: BexPayloadFormat::None, payload: Vec::new(), error_code: "CANCELLED".to_string(), error_message: "Request was cancelled".to_string(), } } }