Skip to main content

levilamina_sys/
lib.rs

1//! Raw FFI declarations mirroring `src/LeviRsAbi.h` (ABI v1).
2//!
3//! This crate contains no logic — only `#[repr(C)]` types. Keep it in
4//! lockstep with the C header: fields are append-only, never reordered.
5//!
6//! You almost certainly want the safe `levilamina` crate instead.
7
8#![no_std]
9#![allow(non_camel_case_types)]
10
11use core::ffi::c_void;
12
13pub const LEVI_RS_ABI_VERSION: u32 = 1;
14pub const LEVI_RS_MAIN_SYMBOL: &str = "levi_rs_main";
15
16/// UTF-8 string view. Not guaranteed NUL-terminated.
17#[repr(C)]
18#[derive(Clone, Copy)]
19pub struct LeviRsStr {
20    pub ptr: *const u8,
21    pub len: usize,
22}
23
24pub type LeviRsModHandle = *mut c_void;
25pub type LeviRsListenerHandle = *mut c_void;
26
27pub type LeviRsTaskCb = unsafe extern "C" fn(user: *mut c_void);
28pub type LeviRsStrSink = unsafe extern "C" fn(ctx: *mut c_void, s: LeviRsStr);
29
30pub type LeviRsEventCb = unsafe extern "C" fn(
31    user: *mut c_void,
32    event_id: LeviRsStr,
33    snbt: LeviRsStr,
34    write_ctx: *mut c_void,
35    write_back: LeviRsStrSink,
36);
37
38pub type LeviRsCommandCb = unsafe extern "C" fn(
39    user: *mut c_void,
40    args: LeviRsStr,
41    origin_name: LeviRsStr,
42    out_ctx: *mut c_void,
43    out_success: LeviRsStrSink,
44    out_error: LeviRsStrSink,
45);
46
47pub type LeviRsCmdOutputSink =
48    unsafe extern "C" fn(ctx: *mut c_void, success: bool, output: LeviRsStr);
49
50/// Function table handed to the Rust mod. Mirrors `LeviRsApi`.
51#[repr(C)]
52pub struct LeviRsApi {
53    pub abi_version: u32,
54    pub struct_size: u32,
55
56    /// level: -1=Off, 0=Fatal, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Trace. Thread-safe.
57    pub log: unsafe extern "C" fn(mod_: LeviRsModHandle, level: i32, msg: LeviRsStr),
58    /// 0=Default, 1=Starting, 2=Running, 3=Stopping. Thread-safe.
59    pub gaming_status: unsafe extern "C" fn() -> i32,
60    /// Queue onto the server thread ASAP. Thread-safe.
61    pub schedule: unsafe extern "C" fn(cb: LeviRsTaskCb, user: *mut c_void),
62    /// Queue onto the server thread after `delay_ms`. Thread-safe.
63    pub schedule_after: unsafe extern "C" fn(cb: LeviRsTaskCb, user: *mut c_void, delay_ms: u64),
64
65    /// Server thread only. priority 0..4 (Highest..Lowest), 2 = Normal.
66    pub subscribe_event: unsafe extern "C" fn(
67        mod_: LeviRsModHandle,
68        event_id: LeviRsStr,
69        priority: i32,
70        cb: LeviRsEventCb,
71        user: *mut c_void,
72    ) -> LeviRsListenerHandle,
73    /// Server thread only.
74    pub unsubscribe_event:
75        unsafe extern "C" fn(mod_: LeviRsModHandle, listener: LeviRsListenerHandle) -> bool,
76    /// Server thread only.
77    pub list_events: unsafe extern "C" fn(ctx: *mut c_void, sink: LeviRsStrSink),
78
79    /// Server thread only. Executes as console (Owner).
80    pub execute_command:
81        unsafe extern "C" fn(cmd: LeviRsStr, ctx: *mut c_void, sink: LeviRsCmdOutputSink) -> bool,
82    /// Server thread only, call during on_enable. permission 0..4.
83    pub register_command: unsafe extern "C" fn(
84        mod_: LeviRsModHandle,
85        name: LeviRsStr,
86        description: LeviRsStr,
87        permission: i32,
88        cb: LeviRsCommandCb,
89        user: *mut c_void,
90    ) -> bool,
91    // ABI v2+: append new fields here only.
92}
93
94/// Filled in by the Rust mod inside `levi_rs_main`. Mirrors `LeviRsModVTable`.
95#[repr(C)]
96pub struct LeviRsModVTable {
97    pub abi_version: u32,
98    pub instance: *mut c_void,
99    pub on_enable: Option<unsafe extern "C" fn(instance: *mut c_void) -> bool>,
100    pub on_disable: Option<unsafe extern "C" fn(instance: *mut c_void) -> bool>,
101    pub on_unload: Option<unsafe extern "C" fn(instance: *mut c_void) -> bool>,
102}
103
104/// The single symbol every Rust mod must export (see `LEVI_RS_MAIN_SYMBOL`).
105/// Mirrors `LeviRsMainFn` in the C header. Provided mainly so the loader's own
106/// `GetProcAddress` cast and any mod-side signature checks share one
107/// definition instead of two hand-written copies drifting apart.
108pub type LeviRsMainFn = unsafe extern "C" fn(
109    api: *const LeviRsApi,
110    self_: LeviRsModHandle,
111    out_vtable: *mut LeviRsModVTable,
112) -> bool;