node-app-api 1.0.1-experimental

Shared types and C ABI definitions for the Node-App host API v1
Documentation
//! C ABI definitions for native app loading
//!
//! All structs in this module use `#[repr(C)]` for stable ABI across
//! Rust, Go, C, C++, and Zig compiled shared libraries.

use std::ffi::c_char;
use std::os::raw::c_void;

/// Symbol name for the app entry point function in shared libraries.
/// Native apps must export this symbol.
pub const NODE_APP_ENTRY_SYMBOL: &[u8] = b"_node_app_entry\0";

/// Result type returned by FFI functions
#[repr(C)]
#[derive(Debug)]
pub struct FfiResult {
    /// Whether the operation succeeded
    pub success: bool,
    /// Error code (0 = no error, negative = app-defined error)
    pub error_code: i32,
    /// Pointer to response data (JSON bytes, caller must free with host_free)
    pub data: *mut u8,
    /// Length of the response data in bytes
    pub data_len: usize,
}

impl FfiResult {
    /// Create a successful result with no data
    pub fn ok() -> Self {
        Self {
            success: true,
            error_code: 0,
            data: std::ptr::null_mut(),
            data_len: 0,
        }
    }

    /// Create an error result
    pub fn error(code: i32) -> Self {
        Self {
            success: false,
            error_code: code,
            data: std::ptr::null_mut(),
            data_len: 0,
        }
    }
}

/// App metadata returned by the entry point function
#[repr(C)]
pub struct NodeAppMetadata {
    /// API version (must match host API_VERSION)
    pub api_version: u32,
    /// App name (null-terminated UTF-8 string, owned by app)
    pub name: *const c_char,
    /// App version (null-terminated UTF-8 string, owned by app)
    pub version: *const c_char,
    /// Author (null-terminated UTF-8 string, owned by app)
    pub author: *const c_char,
    /// Description (null-terminated UTF-8 string, owned by app)
    pub description: *const c_char,
    /// Capability flags (bitwise OR of Capabilities values)
    pub capabilities: u32,
}

/// VTable of function pointers for app operations.
/// Returned by the `_node_app_entry` symbol.
#[repr(C)]
pub struct NodeAppVTable {
    /// App metadata
    pub metadata: NodeAppMetadata,
    /// Initialize the app with the host context.
    /// Called once after loading. Returns FfiResult.
    pub init: unsafe extern "C" fn(ctx: *const c_void) -> FfiResult,
    /// Shut down the app gracefully.
    /// Called before unloading the shared library.
    pub shutdown: unsafe extern "C" fn() -> FfiResult,
    /// Handle an HTTP request.
    /// `request_json` is a pointer to UTF-8 JSON bytes of length `request_len`.
    /// Returns FfiResult with response JSON in `data`/`data_len`.
    pub handle_request:
        unsafe extern "C" fn(request_json: *const u8, request_len: usize) -> FfiResult,
    /// Handle a domain event.
    /// `event_json` is a pointer to UTF-8 JSON bytes of length `event_len`.
    /// Returns FfiResult (data is typically empty for events).
    pub handle_event: unsafe extern "C" fn(event_json: *const u8, event_len: usize) -> FfiResult,
    /// Handle a capability invocation from the capability router.
    /// `request_json` is a pointer to UTF-8 JSON bytes (CapabilityRequest) of length `request_len`.
    /// Returns FfiResult with CapabilityResponse JSON in `data`/`data_len`.
    /// Response is limited to 16MB.
    pub handle_capability:
        unsafe extern "C" fn(request_json: *const u8, request_len: usize) -> FfiResult,
    /// Free memory allocated by the app (for response data).
    /// The host calls this to release `FfiResult.data`.
    pub free: unsafe extern "C" fn(ptr: *mut u8, len: usize),
}

// Safety: NodeAppMetadata contains *const c_char pointers that point to
// static CStrings owned by the plugin. They are effectively immutable
// once the vtable is constructed and valid for the process lifetime.
unsafe impl Send for NodeAppMetadata {}
unsafe impl Sync for NodeAppMetadata {}

// Safety: NodeAppVTable contains function pointers (inherently thread-safe)
// and a NodeAppMetadata with static CString pointers. Once constructed,
// the vtable is immutable and safe to share across threads.
unsafe impl Send for NodeAppVTable {}
unsafe impl Sync for NodeAppVTable {}

/// Type signature for the `_node_app_entry` function exported by native apps.
/// Returns a pointer to a static NodeAppVTable.
pub type NodeAppEntryFn = unsafe extern "C" fn(ctx: *const c_void) -> *const NodeAppVTable;