Skip to main content

code_native/
abi.rs

1//! Vendored copy of `code-abi`'s C-ABI contract.
2//!
3//! `code-abi` is the canonical, single source of truth for this ABI (used
4//! directly by the host runtime: `native_module.rs`, `wasm_module.rs`), but it
5//! stays unpublished (`publish = false`) on purpose. `code-native` — the
6//! authoring SDK for native modules — needs to be publishable to crates.io on
7//! its own, and crates.io rejects packages with a path dependency on an
8//! unpublished crate.
9//!
10//! This file is therefore a literal, mechanically-kept-in-sync copy of
11//! `crates/code-abi/src/lib.rs`. **Do not hand-edit it** — edit `code-abi`,
12//! then copy its `src/lib.rs` here verbatim (only the header comment and the
13//! crate-level `#![no_std]` attribute differ, since this is a module, not its
14//! own crate). `tests/abi_in_sync.rs` fails the build if the two diverge.
15
16use core::ffi::{c_char, c_void};
17
18// ===========================================================================
19// ABI version + target constants
20// ===========================================================================
21
22/// Current ABI version. Native modules must return this from
23/// `code_module_abi_version`.
24pub const CODE_ABI_VERSION: u32 = 2;
25
26/// Emission target: dispatch to the linking module's base handlers.
27pub const CODE_EMIT_TARGET_BASE: u32 = 0;
28
29// ===========================================================================
30// Value tag constants (must match the codegen tags)
31// ===========================================================================
32
33pub const CODE_TAG_NUMBER: u8 = 0;
34pub const CODE_TAG_STRING: u8 = 1;
35pub const CODE_TAG_BOOLEAN: u8 = 2;
36pub const CODE_TAG_OBJECT: u8 = 3;
37pub const CODE_TAG_NULL: u8 = 4;
38pub const CODE_TAG_ARRAY: u8 = 5;
39
40// ===========================================================================
41// C-ABI struct definitions (repr(C) — mirrored in code_abi.h)
42// ===========================================================================
43
44/// A single Code value in C-ABI representation.
45///
46/// Active fields depend on `tag`:
47/// - `CODE_TAG_NUMBER`  → `number`
48/// - `CODE_TAG_STRING`  → `string` (null-terminated UTF-8 C string)
49/// - `CODE_TAG_BOOLEAN` → `boolean` (0 = false, non-zero = true)
50/// - `CODE_TAG_OBJECT`  → `fields` + `field_count`
51/// - `CODE_TAG_NULL`    → (no data)
52/// - `CODE_TAG_ARRAY`   → `elements` + `element_count`
53#[repr(C)]
54pub struct CodeValue {
55    pub tag: u8,
56    pub number: f64,
57    pub string: *const c_char,
58    pub boolean: u8,
59    pub fields: *const CodeField,
60    pub field_count: u32,
61    pub elements: *const CodeValue,
62    pub element_count: u32,
63}
64
65impl CodeValue {
66    /// Create a null `CodeValue` with all fields zeroed.
67    pub fn null() -> Self {
68        CodeValue {
69            tag: CODE_TAG_NULL,
70            number: 0.0,
71            string: core::ptr::null(),
72            boolean: 0,
73            fields: core::ptr::null(),
74            field_count: 0,
75            elements: core::ptr::null(),
76            element_count: 0,
77        }
78    }
79}
80
81/// A key-value pair for object fields.
82#[repr(C)]
83pub struct CodeField {
84    pub name: *const c_char,
85    pub value: CodeValue,
86}
87
88// ---------------------------------------------------------------------------
89// Function / handler signatures
90// ---------------------------------------------------------------------------
91
92/// Native handler signature: `fn(particle) -> CodeValue`.
93pub type CodeNativeHandlerFn = unsafe extern "C" fn(particle: CodeValue) -> CodeValue;
94
95/// Callback signature for native-module emission.
96pub type CodeEmitFn = unsafe extern "C" fn(context: *mut c_void, particle: CodeValue);
97
98// ---------------------------------------------------------------------------
99// Export descriptor types
100// ---------------------------------------------------------------------------
101
102/// Exported variable: name + constant value.
103#[repr(C)]
104pub struct CodeExportVar {
105    pub name: *const c_char,
106    pub value: CodeValue,
107}
108
109/// Exported handler: class name + handler function.
110#[repr(C)]
111pub struct CodeExportHandler {
112    pub class_name: *const c_char,
113    pub handler: CodeNativeHandlerFn,
114}
115
116/// Field descriptor for type declarations.
117#[repr(C)]
118pub struct CodeTypeField {
119    pub name: *const c_char,
120    /// Type name as C string, e.g. "String", "Number".
121    pub type_name: *const c_char,
122    /// 0 = required, non-zero = optional.
123    pub is_optional: u8,
124}
125
126/// Exported type declaration.
127#[repr(C)]
128pub struct CodeExportType {
129    pub name: *const c_char,
130    pub fields: *const CodeTypeField,
131    pub field_count: u32,
132}
133
134/// Emission declaration exported by a native module.
135#[repr(C)]
136pub struct CodeEmission {
137    pub class_name: *const c_char,
138    /// 0 = base (dispatch to linking module's handlers).
139    pub target: u32,
140}
141
142/// Top-level module descriptor returned by `code_module_init()`.
143#[repr(C)]
144pub struct CodeModuleDesc {
145    pub abi_version: u32,
146    pub vars: *const CodeExportVar,
147    pub var_count: u32,
148    pub handlers: *const CodeExportHandler,
149    pub handler_count: u32,
150    pub types: *const CodeExportType,
151    pub type_count: u32,
152    pub emissions: *const CodeEmission,
153    pub emission_count: u32,
154}
155
156// ---------------------------------------------------------------------------
157// Safety: these types contain raw pointers but are only used as immutable
158// descriptors shared across threads. The module init function is called once
159// and the data is read-only after that.
160// ---------------------------------------------------------------------------
161
162unsafe impl Sync for CodeValue {}
163unsafe impl Send for CodeValue {}
164unsafe impl Sync for CodeField {}
165unsafe impl Send for CodeField {}
166unsafe impl Sync for CodeExportVar {}
167unsafe impl Send for CodeExportVar {}
168unsafe impl Sync for CodeExportHandler {}
169unsafe impl Send for CodeExportHandler {}
170unsafe impl Sync for CodeTypeField {}
171unsafe impl Send for CodeTypeField {}
172unsafe impl Sync for CodeExportType {}
173unsafe impl Send for CodeExportType {}
174unsafe impl Sync for CodeEmission {}
175unsafe impl Send for CodeEmission {}
176unsafe impl Sync for CodeModuleDesc {}
177unsafe impl Send for CodeModuleDesc {}