Skip to main content

foundation_models/ffi/
mod.rs

1//! Raw FFI declarations matching the Swift `@_cdecl` exports in
2//! `swift-bridge/Sources/FoundationModelsBridge`.
3//!
4//! These are intentionally opaque (`*mut c_void`) and unsafe; safe wrappers
5//! live in the parent modules.
6
7use core::ffi::{c_char, c_void};
8
9/// Plain-old-data carrier for [`crate::generation::GenerationOptions`].
10#[derive(Copy, Clone, Debug)]
11pub struct FFIGenerationOptions {
12    pub temperature: f64,
13    pub maximum_response_tokens: i32,
14    pub sampling_mode: i32,
15    pub top_k: i32,
16    pub top_p: f64,
17    pub random_seed: u64,
18    pub has_random_seed: bool,
19}
20
21pub type FmRespondCallback = unsafe extern "C" fn(
22    context: *mut c_void,
23    response: *mut c_char,
24    error: *mut c_char,
25    status: i32,
26);
27
28/// 3-argument async callback used by the `async_api` thunks in `Async.swift`.
29///
30/// - `result`  Non-null on success; semantics are thunk-specific (opaque pointer or C string).
31/// - `error`   Non-null null-terminated UTF-8 error message on failure.
32/// - `ctx`     Opaque context pointer from `AsyncCompletion::create()`.
33pub type FmAsyncCallback = unsafe extern "C" fn(
34    result: *mut c_void,
35    error: *const c_char,
36    ctx: *mut c_void,
37);
38
39pub type FmStreamCallback =
40    unsafe extern "C" fn(context: *mut c_void, chunk: *mut c_char, done: bool, status: i32);
41
42pub type FmToolCallback = unsafe extern "C" fn(
43    context: *mut c_void,
44    tool_name: *const c_char,
45    arguments_json: *const c_char,
46    output_json_out: *mut *mut c_char,
47    error_out: *mut *mut c_char,
48) -> i32;
49
50extern "C" {
51    pub fn fm_string_dup(s: *const c_char) -> *mut c_char;
52    pub fn fm_string_free(s: *mut c_char);
53    pub fn fm_bytes_free(ptr: *mut c_void);
54    pub fn fm_object_release(ptr: *mut c_void);
55
56    pub fn fm_system_model_is_available() -> bool;
57    pub fn fm_system_model_availability_code() -> i32;
58    pub fn fm_system_model_create_default() -> *mut c_void;
59    pub fn fm_system_model_create(
60        use_case: i32,
61        guardrails: i32,
62        error_out: *mut *mut c_char,
63    ) -> *mut c_void;
64    pub fn fm_system_model_create_with_adapter(
65        adapter: *mut c_void,
66        guardrails: i32,
67        error_out: *mut *mut c_char,
68    ) -> *mut c_void;
69    pub fn fm_system_model_availability_code_for(model: *mut c_void) -> i32;
70    pub fn fm_system_model_supported_languages_json(model: *mut c_void) -> *mut c_char;
71    pub fn fm_system_model_supports_locale(
72        model: *mut c_void,
73        locale_identifier: *const c_char,
74    ) -> bool;
75
76    pub fn fm_adapter_create_from_file(
77        file_path: *const c_char,
78        error_out: *mut *mut c_char,
79    ) -> *mut c_void;
80    pub fn fm_adapter_create_from_name(
81        name: *const c_char,
82        error_out: *mut *mut c_char,
83    ) -> *mut c_void;
84    pub fn fm_adapter_compile(
85        adapter: *mut c_void,
86        context: *mut c_void,
87        callback: FmRespondCallback,
88    );
89    pub fn fm_adapter_compatible_identifiers_json(name: *const c_char) -> *mut c_char;
90    pub fn fm_adapter_remove_obsolete(error_out: *mut *mut c_char) -> i32;
91    pub fn fm_adapter_metadata_json(adapter: *mut c_void) -> *mut c_char;
92
93    pub fn fm_session_create(instructions: *const c_char) -> *mut c_void;
94    pub fn fm_session_create_ex(
95        model: *mut c_void,
96        instructions_json: *const c_char,
97        transcript_json: *const c_char,
98        tools_json: *const c_char,
99        tool_context: *mut c_void,
100        tool_callback: Option<FmToolCallback>,
101        error_out: *mut *mut c_char,
102    ) -> *mut c_void;
103
104    pub fn fm_session_respond(
105        session: *mut c_void,
106        prompt: *const c_char,
107        temperature: f64,
108        max_tokens: i32,
109        sampling_mode: i32,
110        top_k: i32,
111        top_p: f64,
112        context: *mut c_void,
113        callback: FmRespondCallback,
114    );
115    pub fn fm_session_respond_request_json(
116        session: *mut c_void,
117        request_json: *const c_char,
118        context: *mut c_void,
119        callback: FmRespondCallback,
120    );
121
122    pub fn fm_session_respond_with_schema(
123        session: *mut c_void,
124        prompt: *const c_char,
125        schema_json: *const c_char,
126        include_schema_in_prompt: bool,
127        temperature: f64,
128        max_tokens: i32,
129        sampling_mode: i32,
130        top_k: i32,
131        top_p: f64,
132        context: *mut c_void,
133        callback: FmRespondCallback,
134    );
135
136    pub fn fm_session_stream_response(
137        session: *mut c_void,
138        prompt: *const c_char,
139        temperature: f64,
140        max_tokens: i32,
141        sampling_mode: i32,
142        top_k: i32,
143        top_p: f64,
144        context: *mut c_void,
145        callback: FmStreamCallback,
146    );
147    pub fn fm_session_stream_request_json(
148        session: *mut c_void,
149        request_json: *const c_char,
150        context: *mut c_void,
151        callback: FmStreamCallback,
152    );
153
154    pub fn fm_session_prewarm(session: *mut c_void);
155    pub fn fm_session_prewarm_prompt_json(
156        session: *mut c_void,
157        prompt_json: *const c_char,
158        error_out: *mut *mut c_char,
159    ) -> i32;
160    pub fn fm_session_is_responding(session: *mut c_void) -> bool;
161    pub fn fm_session_transcript_json(session: *mut c_void) -> *mut c_char;
162    pub fn fm_session_log_feedback(
163        session: *mut c_void,
164        sentiment: i32,
165        description: *const c_char,
166    );
167    pub fn fm_session_log_feedback_attachment_json(
168        session: *mut c_void,
169        request_json: *const c_char,
170        length_out: *mut usize,
171        error_out: *mut *mut c_char,
172    ) -> *mut c_void;
173
174    pub fn fm_generation_schema_compile_json(
175        request_json: *const c_char,
176        context: *mut c_void,
177        callback: FmRespondCallback,
178    );
179    pub fn fm_generation_schema_validate_json(
180        schema_json: *const c_char,
181        error_out: *mut *mut c_char,
182    ) -> i32;
183
184    pub fn fm_generation_id_create(
185        output_out: *mut *mut c_char,
186        error_out: *mut *mut c_char,
187    ) -> i32;
188    pub fn fm_decimal_to_generated_content_json(
189        decimal_string: *const c_char,
190        output_out: *mut *mut c_char,
191        error_out: *mut *mut c_char,
192    ) -> i32;
193    pub fn fm_decimal_from_generated_content_json(
194        generated_content_json: *const c_char,
195        output_out: *mut *mut c_char,
196        error_out: *mut *mut c_char,
197    ) -> i32;
198    pub fn fm_refusal_explanation_json(
199        refusal_token: *const c_char,
200        context: *mut c_void,
201        callback: FmRespondCallback,
202    );
203    pub fn fm_refusal_explanation_from_transcript_json(
204        transcript_json: *const c_char,
205        context: *mut c_void,
206        callback: FmRespondCallback,
207    );
208    pub fn fm_refusal_explanation_stream(
209        refusal_token: *const c_char,
210        context: *mut c_void,
211        callback: FmStreamCallback,
212    );
213    pub fn fm_refusal_explanation_stream_from_transcript_json(
214        transcript_json: *const c_char,
215        context: *mut c_void,
216        callback: FmStreamCallback,
217    );
218
219    // ── Async thunks (Async.swift) ─────────────────────────────────────────
220
221    /// Async version of `Adapter(name:)`.
222    ///
223    /// Calls `cb(retainedAdapterBoxPtr, nil, ctx)` on success or
224    /// `cb(nil, errorCStr, ctx)` on failure.
225    /// Free the result with `fm_object_release`; errors are stack-owned by the callback.
226    pub fn fm_adapter_create_from_name_async(
227        name: *const c_char,
228        ctx: *mut c_void,
229        cb: FmAsyncCallback,
230    );
231
232    /// Async version of `Adapter.compatibleAdapterIdentifiers(name:)`.
233    ///
234    /// Calls `cb(strdupJsonPtr, nil, ctx)` on success where the pointer is a
235    /// heap-allocated UTF-8 JSON array.  Free it with `fm_string_free`.
236    /// On failure calls `cb(nil, errorCStr, ctx)`.
237    pub fn fm_adapter_compatibility_async(
238        name: *const c_char,
239        ctx: *mut c_void,
240        cb: FmAsyncCallback,
241    );
242}
243
244/// Status codes mirrored 1:1 from the `FM_*` constants in Swift.
245pub mod status {
246    pub const OK: i32 = 0;
247    pub const INVALID_ARGUMENT: i32 = -1;
248    pub const MODEL_UNAVAILABLE: i32 = -2;
249    pub const CANCELLED: i32 = -3;
250    pub const GUARDRAIL_VIOLATION: i32 = -4;
251    pub const CONTEXT_WINDOW_EXCEEDED: i32 = -5;
252    pub const UNSUPPORTED_LANGUAGE: i32 = -6;
253    pub const ASSETS_UNAVAILABLE: i32 = -7;
254    pub const RATE_LIMITED: i32 = -8;
255    pub const DECODING_FAILURE: i32 = -9;
256    pub const REFUSAL: i32 = -10;
257    pub const CONCURRENT_REQUESTS: i32 = -11;
258    pub const UNSUPPORTED_GUIDE: i32 = -12;
259    pub const TOOL_CALL_FAILED: i32 = -13;
260    pub const ADAPTER_INVALID_ASSET: i32 = -14;
261    pub const ADAPTER_INVALID_NAME: i32 = -15;
262    pub const ADAPTER_COMPATIBLE_NOT_FOUND: i32 = -16;
263    pub const UNKNOWN: i32 = -99;
264}