Skip to main content

node_app_api/
ffi.rs

1//! C ABI definitions for native app loading
2//!
3//! All structs in this module use `#[repr(C)]` for stable ABI across
4//! Rust, Go, C, C++, and Zig compiled shared libraries.
5
6use std::ffi::c_char;
7use std::os::raw::c_void;
8
9/// Symbol name for the app entry point function in shared libraries.
10/// Native apps must export this symbol.
11pub const NODE_APP_ENTRY_SYMBOL: &[u8] = b"_node_app_entry\0";
12
13/// Result type returned by FFI functions
14#[repr(C)]
15#[derive(Debug)]
16pub struct FfiResult {
17    /// Whether the operation succeeded
18    pub success: bool,
19    /// Error code (0 = no error, negative = app-defined error)
20    pub error_code: i32,
21    /// Pointer to response data (JSON bytes, caller must free with host_free)
22    pub data: *mut u8,
23    /// Length of the response data in bytes
24    pub data_len: usize,
25}
26
27impl FfiResult {
28    /// Create a successful result with no data
29    pub fn ok() -> Self {
30        Self {
31            success: true,
32            error_code: 0,
33            data: std::ptr::null_mut(),
34            data_len: 0,
35        }
36    }
37
38    /// Create an error result
39    pub fn error(code: i32) -> Self {
40        Self {
41            success: false,
42            error_code: code,
43            data: std::ptr::null_mut(),
44            data_len: 0,
45        }
46    }
47}
48
49/// App metadata returned by the entry point function
50#[repr(C)]
51pub struct NodeAppMetadata {
52    /// API version (must match host API_VERSION)
53    pub api_version: u32,
54    /// App name (null-terminated UTF-8 string, owned by app)
55    pub name: *const c_char,
56    /// App version (null-terminated UTF-8 string, owned by app)
57    pub version: *const c_char,
58    /// Author (null-terminated UTF-8 string, owned by app)
59    pub author: *const c_char,
60    /// Description (null-terminated UTF-8 string, owned by app)
61    pub description: *const c_char,
62    /// Capability flags (bitwise OR of Capabilities values)
63    pub capabilities: u32,
64}
65
66/// VTable of function pointers for app operations.
67/// Returned by the `_node_app_entry` symbol.
68#[repr(C)]
69pub struct NodeAppVTable {
70    /// App metadata
71    pub metadata: NodeAppMetadata,
72    /// Initialize the app with the host context.
73    /// Called once after loading. Returns FfiResult.
74    pub init: unsafe extern "C" fn(ctx: *const c_void) -> FfiResult,
75    /// Shut down the app gracefully.
76    /// Called before unloading the shared library.
77    pub shutdown: unsafe extern "C" fn() -> FfiResult,
78    /// Handle an HTTP request.
79    /// `request_json` is a pointer to UTF-8 JSON bytes of length `request_len`.
80    /// Returns FfiResult with response JSON in `data`/`data_len`.
81    pub handle_request:
82        unsafe extern "C" fn(request_json: *const u8, request_len: usize) -> FfiResult,
83    /// Handle a domain event.
84    /// `event_json` is a pointer to UTF-8 JSON bytes of length `event_len`.
85    /// Returns FfiResult (data is typically empty for events).
86    pub handle_event: unsafe extern "C" fn(event_json: *const u8, event_len: usize) -> FfiResult,
87    /// Handle a capability invocation from the capability router.
88    /// `request_json` is a pointer to UTF-8 JSON bytes (CapabilityRequest) of length `request_len`.
89    /// Returns FfiResult with CapabilityResponse JSON in `data`/`data_len`.
90    /// Response is limited to 16MB.
91    pub handle_capability:
92        unsafe extern "C" fn(request_json: *const u8, request_len: usize) -> FfiResult,
93    /// Free memory allocated by the app (for response data).
94    /// The host calls this to release `FfiResult.data`.
95    pub free: unsafe extern "C" fn(ptr: *mut u8, len: usize),
96}
97
98// Safety: NodeAppMetadata contains *const c_char pointers that point to
99// static CStrings owned by the plugin. They are effectively immutable
100// once the vtable is constructed and valid for the process lifetime.
101unsafe impl Send for NodeAppMetadata {}
102unsafe impl Sync for NodeAppMetadata {}
103
104// Safety: NodeAppVTable contains function pointers (inherently thread-safe)
105// and a NodeAppMetadata with static CString pointers. Once constructed,
106// the vtable is immutable and safe to share across threads.
107unsafe impl Send for NodeAppVTable {}
108unsafe impl Sync for NodeAppVTable {}
109
110/// Type signature for the `_node_app_entry` function exported by native apps.
111/// Returns a pointer to a static NodeAppVTable.
112pub type NodeAppEntryFn = unsafe extern "C" fn(ctx: *const c_void) -> *const NodeAppVTable;