Skip to main content

dittolive_ditto_sys/
dittoffi.rs

1//! C headers written in Rust.
2
3use ::safer_ffi::{closure::boxed::*, prelude::derive_ReprC};
4
5use super::*;
6use crate::ffi_utils::repr_c;
7
8// Ditto initialization API
9#[apply(extern_type_polyfill!)]
10unsafe extern "C" {
11    pub fn dittoffi_ditto_open_async_throws(
12        config_cbor: c_slice::Ref<'_, u8>,
13        transport_config_mode: TransportConfigMode,
14        default_root_directory: char_p::Ref<'_>,
15        continuation: BoxDynFnMut1<(), FfiResult<repr_c::Box<Ditto>>>,
16    );
17
18    pub fn dittoffi_ditto_open_throws(
19        config_cbor: c_slice::Ref<'_, u8>,
20        transport_config_mode: TransportConfigMode,
21        default_root_directory: char_p::Ref<'_>,
22    ) -> FfiResult<repr_c::Box<Ditto>>;
23
24    pub fn dittoffi_ditto_config(ditto: &Ditto) -> c_slice::Box<u8>;
25
26    pub fn dittoffi_ditto_absolute_persistence_directory(ditto: &Ditto) -> char_p::Box;
27}
28
29#[repr(C)]
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub enum TransportConfigMode {
32    PlatformDependent,
33    PlatformIndependent,
34}
35
36#[apply(extern_type_polyfill!)]
37unsafe extern "C" {
38    // we need to let the build.rs script control the dylib vs. static choice
39    pub type Ditto: Send + Sync;
40    #[drop(to impl FfiDropBox for Ditto)]
41    pub fn ditto_free(ditto: c::Box<Ditto>);
42
43    pub fn ditto_shutdown(ditto: &'_ Ditto);
44
45    pub fn ditto_init_sdk_version(
46        platform: Platform,
47        language: Language,
48        sdk_semver: char_p::Ref<'_>,
49    );
50
51    pub type IdentityConfig: Send + Sync;
52
53    pub fn ditto_make(
54        working_dir: char_p::Ref<'_>,
55        identity_config: c::Box<IdentityConfig>,
56        history_tracking: HistoryTracking,
57    ) -> c::Box<Ditto>;
58
59    pub fn ditto_logger_init();
60    pub fn ditto_logger_enabled(enabled: bool);
61    pub fn ditto_logger_enabled_get() -> bool;
62    pub fn ditto_logger_emoji_headings_enabled(enabled: bool);
63    pub fn ditto_logger_emoji_headings_enabled_get() -> bool;
64    pub fn ditto_logger_minimum_log_level_get() -> CLogLevel;
65    pub fn ditto_logger_minimum_log_level(log_level: CLogLevel);
66    pub fn ditto_log(log_level: CLogLevel, msg: char_p::Ref<'_>);
67
68    pub unsafe fn ditto_sdk_transports_init(out_error: Out<'_, DittoSdkTransportsError>) -> bool;
69
70    pub fn ditto_get_sdk_version() -> char_p::Box;
71
72    pub fn ditto_verify_license(
73        ditto: &'_ Ditto,
74        license: char_p::Ref<'_>,
75        out_err_msg: Option<Out<'_, Option<char_p::Box>>>,
76    ) -> LicenseVerificationResult;
77
78    pub fn ditto_run_garbage_collection(ditto: &'_ Ditto);
79
80    pub fn ditto_disable_sync_with_v3(ditto: &'_ Ditto) -> c_int;
81
82    pub fn ditto_get_collection_names(ditto: &'_ Ditto) -> c::Result_Vec<char_p::Box>;
83
84    pub fn ditto_queries_hash<'s, 'l: 's>(
85        ditto: &Ditto,
86        coll_names: c_slice::Ref<'s, char_p::Ref<'l>>,
87        queries: c_slice::Ref<'s, char_p::Ref<'l>>,
88    ) -> c::Result<u64>;
89
90    pub fn ditto_queries_hash_mnemonic<'s, 'l: 's>(
91        ditto: &'_ Ditto,
92        coll_names: c_slice::Ref<'s, char_p::Ref<'l>>,
93        queries: c_slice::Ref<'s, char_p::Ref<'l>>,
94    ) -> c::Result<char_p::Box>;
95
96    pub fn ditto_collection(ditto: &'_ Ditto, name: char_p::Ref<'_>) -> c_int;
97
98    pub fn ditto_collection_insert_value(
99        ditto: &'_ Ditto,
100        coll_name: char_p::Ref<'_>,
101        doc_cbor: c_slice::Ref<'_, u8>,
102        write_strategy: WriteStrategyRs,
103        log_hint: Option<char_p::Ref<'_>>,
104        txn: Option<&'_ mut CWriteTransaction>,
105    ) -> c::Result_BoxedSlice<u8>;
106
107    pub fn ditto_collection_update(
108        ditto: &'_ Ditto,
109        coll_name: char_p::Ref<'_>,
110        transaction: &'_ mut CWriteTransaction,
111        document: c::Box<Document>,
112    ) -> c_int;
113
114    pub fn ditto_collection_evict(
115        ditto: &'_ Ditto,
116        coll_name: char_p::Ref<'_>,
117        transaction: &'_ mut CWriteTransaction,
118        id: c_slice::Ref<'_, u8>,
119    ) -> c::Result<bool>;
120
121    pub fn ditto_collection_remove(
122        ditto: &'_ Ditto,
123        coll_name: char_p::Ref<'_>,
124        transaction: &'_ mut CWriteTransaction,
125        id: c_slice::Ref<'_, u8>,
126    ) -> c::Result<bool>;
127
128    pub fn ditto_collection_get(
129        ditto: &'_ Ditto,
130        coll_name: char_p::Ref<'_>,
131        id: c_slice::Ref<'_, u8>,
132        transaction: &'_ mut CReadTransaction,
133    ) -> c::Result_Box<Document>;
134
135    pub fn ditto_collection_get_with_write_transaction(
136        ditto: &'_ Ditto,
137        coll_name: char_p::Ref<'_>,
138        id: c_slice::Ref<'_, u8>,
139        transaction: &'_ mut CWriteTransaction,
140    ) -> c::Result_Box<Document>;
141
142    pub fn ditto_collection_exec_query_str<'order_ref, 'order: 'order_ref>(
143        ditto: &'_ Ditto,
144        coll_name: char_p::Ref<'_>,
145        txn: Option<&'_ mut CWriteTransaction>,
146        query: char_p::Ref<'_>,
147        query_args: Option<c_slice::Ref<'_, u8>>,
148        order_by_params: c_slice::Ref<'order_ref, COrderByParam<'order>>,
149        limit: c_int,
150        offset: c_uint,
151    ) -> c::Result_Vec<c::Box<Document>>;
152
153    pub fn ditto_collection_remove_query_str<'order_ref, 'order: 'order_ref>(
154        ditto: &'_ Ditto,
155        coll_name: char_p::Ref<'_>,
156        transaction: &'_ mut CWriteTransaction,
157        query: char_p::Ref<'_>,
158        query_args: Option<c_slice::Ref<'_, u8>>,
159        order_by_params: c_slice::Ref<'order_ref, COrderByParam<'order>>,
160        limit: c_int,
161        offset: c_uint,
162    ) -> c::Result_Vec<c_slice::Box<u8>>;
163
164    pub fn ditto_collection_evict_query_str<'order_ref, 'order: 'order_ref>(
165        ditto: &'_ Ditto,
166        coll_name: char_p::Ref<'_>,
167        transaction: &'_ mut CWriteTransaction,
168        query: char_p::Ref<'_>,
169        query_args: Option<c_slice::Ref<'_, u8>>,
170        order_by_params: c_slice::Ref<'order_ref, COrderByParam<'order>>,
171        limit: c_int,
172        offset: c_uint,
173    ) -> c::Result_Vec<c_slice::Box<u8>>;
174
175    pub fn ditto_read_transaction<'txn>(ditto: &'_ Ditto) -> c::Result_Box<CReadTransaction>;
176
177    pub type CReadTransaction;
178    #[drop(to impl FfiDropBox for CReadTransaction)]
179    pub fn ditto_read_transaction_free(transaction: c::Box<CReadTransaction>);
180
181    pub fn ditto_write_transaction(
182        ditto: &'_ Ditto,
183        log_hint: Option<char_p::Ref<'_>>,
184    ) -> c::Result_Box<CWriteTransaction>;
185
186    pub type CWriteTransaction;
187    #[drop(to impl FfiDropBox for CWriteTransaction)]
188    pub fn ditto_write_transaction_free(txn: c::Box<CWriteTransaction>);
189
190    pub fn ditto_write_transaction_commit(
191        ditto: &Ditto,
192        transaction: c::Box<CWriteTransaction>,
193    ) -> c_int;
194
195    pub fn ditto_write_transaction_rollback(ditto: &Ditto, transaction: c::Box<CWriteTransaction>);
196
197    pub fn ditto_document_id(document: &'_ Document) -> c_slice::Box<u8>;
198
199    pub fn ditto_document_id_query_compatible(
200        id: c_slice::Ref<'_, u8>,
201        string_primitive_format: StringPrimitiveFormat,
202    ) -> char_p::Box;
203
204    pub fn ditto_validate_document_id(
205        cbor: c_slice::Ref<'_, u8>,
206        out_cbor: Out<'_, Option<c_slice::Box<u8>>>,
207    ) -> c_uint;
208
209    pub fn ditto_add_subscription<'s, 'l: 's>(
210        ditto: &'_ Ditto,
211        collection: char_p::Ref<'_>,
212        query: char_p::Ref<'_>,
213        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
214        order_by: c_slice::Ref<'s, COrderByParam<'l>>,
215        limit: c_int,
216        offset: c_uint,
217    ) -> c_int;
218
219    pub fn ditto_remove_subscription<'s, 'l: 's>(
220        ditto: &'_ Ditto,
221        collection: char_p::Ref<'_>,
222        query: char_p::Ref<'_>,
223        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
224        order_by: c_slice::Ref<'s, COrderByParam<'l>>,
225        limit: c_int,
226        offset: c_uint,
227    ) -> c_int;
228
229    pub unsafe fn ditto_live_query_register_str<'s, 'l: 's>(
230        ditto: &'_ Ditto,
231        coll_name: char_p::Ref<'_>,
232        query: char_p::Ref<'_>,
233        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
234        order_by: c_slice::Ref<'s, COrderByParam<'l>>,
235        limit: c_int,
236        offset: c_uint,
237        lq_availability: LiveQueryAvailability,
238        ctx: *mut c_void,
239        retain: Option<unsafe extern "C" fn(*mut c_void)>,
240        release: Option<unsafe extern "C" fn(*mut c_void)>,
241        c_cb: unsafe extern "C" fn(ctx: *mut c_void, params: ChangeHandlerWithDocsDiff),
242    ) -> c::Result<i64>;
243
244    pub fn ditto_live_query_start(ditto: &'_ Ditto, id: i64) -> c_int;
245
246    pub fn ditto_live_query_stop(ditto: &'_ Ditto, id: i64);
247
248    pub fn ditto_live_query_signal_available_next(ditto: &'_ Ditto, id: i64);
249
250    pub fn ditto_documents_hash(documents: c_slice::Ref<'_, c::Box<Document>>) -> c::Result<u64>;
251
252    pub fn ditto_documents_hash_mnemonic(
253        documents: c_slice::Ref<'_, c::Box<Document>>,
254    ) -> c::Result<char_p::Box>;
255
256    pub fn ditto_new_attachment_from_file(
257        ditto: &'_ Ditto,
258        source_path: char_p::Ref<'_>,
259        file_operation: AttachmentFileOperation,
260        out_attachment: Out<'_, Attachment>,
261    ) -> c_uint;
262
263    pub fn ditto_new_attachment_from_bytes(
264        ditto: &'_ Ditto,
265        bytes: c_slice::Ref<'_, u8>,
266        out_attachment: Out<'_, Attachment>,
267    ) -> c_uint;
268
269    pub fn ditto_get_complete_attachment_path(
270        ditto: &'_ Ditto,
271        handle: &'_ AttachmentHandle,
272    ) -> char_p::Box;
273
274    pub unsafe fn ditto_resolve_attachment(
275        ditto: &'_ Ditto,
276        id: c_slice::Ref<'_, u8>,
277        ctx: *mut c_void,
278        retain: Option<unsafe extern "C" fn(*mut c_void)>,
279        release: Option<unsafe extern "C" fn(*mut c_void)>,
280        on_complete_cb: unsafe extern "C" fn(ctx: *mut c_void, c::Box<AttachmentHandle>),
281        on_progress_cb: unsafe extern "C" fn(ctx: *mut c_void, u64, u64),
282        on_deleted_cb: unsafe extern "C" fn(ctx: *mut c_void),
283    ) -> c::Result<u64>;
284
285    pub fn ditto_cancel_resolve_attachment(
286        ditto: &'_ Ditto,
287        id: c_slice::Ref<'_, u8>,
288        cancel_token: u64,
289    ) -> c_uint;
290
291    pub fn ditto_document_update(document: &'_ mut Document, cbor: c_slice::Ref<'_, u8>) -> c_int;
292
293    pub fn ditto_collection_update_multiple(
294        ditto: &'_ Ditto,
295        coll_name: char_p::Ref<'_>,
296        transaction: &'_ mut CWriteTransaction,
297        documents: c::Vec<c::Box<Document>>,
298    ) -> c_int;
299
300    pub type FfiError: Send + Sync;
301    pub fn dittoffi_error_code(_error: &'_ FfiError) -> FfiErrorCode;
302
303    pub fn dittoffi_error_description(_error: &'_ FfiError) -> char_p::Box;
304
305    #[drop(to impl FfiDropBox for FfiError)]
306    pub fn dittoffi_error_free(_error: c::Box<FfiError>);
307
308    pub fn ditto_error_message() -> Option<char_p::Box>;
309
310    pub fn ditto_document_cbor(document: &'_ Document) -> c_slice::Box<u8>;
311
312    pub fn ditto_document_get_cbor_with_path_type(
313        document: &'_ Document,
314        pointer: char_p::Ref<'_>,
315        path_type: PathAccessorType,
316    ) -> c::Result_OptionBoxedSlice<u8>;
317
318    pub fn ditto_document_get_variant_cbor(
319        document: &'_ Document,
320        pointer: char_p::Ref<'_>,
321        variant: DittoCrdtType,
322    ) -> c::Result_BoxedSlice<u8>;
323
324    pub fn ditto_document_set_cbor(
325        document: &'_ mut Document,
326        pointer: char_p::Ref<'_>,
327        cbor: c_slice::Ref<'_, u8>,
328    ) -> c_int;
329
330    pub fn ditto_document_set_cbor_with_timestamp(
331        document: &'_ mut Document,
332        pointer: char_p::Ref<'_>,
333        cbor: c_slice::Ref<'_, u8>,
334        timestamp: c_uint,
335    ) -> c_int;
336
337    pub fn ditto_document_remove(document: &'_ mut Document, pointer: char_p::Ref<'_>) -> c_int;
338
339    pub type Document: Send + Sync;
340    #[drop(to impl FfiDropBox for Document)]
341    pub fn ditto_document_free(document: c::Box<Document>);
342
343    pub fn ditto_document_increment_counter(
344        document: &'_ mut Document,
345        pointer: char_p::Ref<'_>,
346        amount: c_double,
347    ) -> c_int;
348
349    pub type AttachmentHandle: Send + Sync;
350    #[drop(to impl FfiDropBox for AttachmentHandle)]
351    pub fn ditto_free_attachment_handle(handle: c::Box<AttachmentHandle>);
352
353    pub type MdnsPlatformHandle: Send + Sync;
354    #[drop(to impl FfiDropBox for MdnsPlatformHandle)]
355    pub fn ditto_mdns_transport_free_handle(handle: c::Box<MdnsPlatformHandle>);
356
357    pub type BlePlatformHandle: Send + Sync;
358    #[drop(to impl FfiDropBox for BlePlatformHandle)]
359    pub fn ditto_ble_transport_free_handle(handle: c::Box<BlePlatformHandle>);
360
361    pub fn ditto_free_indices(indices: Option<c_slice::Box<usize>>);
362
363    pub fn ditto_c_string_free(s: char_p::Box);
364
365    pub fn ditto_c_bytes_free(bytes: c_slice::Box<u8>);
366
367    pub fn ditto_identity_config_make_online_with_authentication(
368        app_id: char_p::Ref<'_>,
369        base_url: char_p::Ref<'_>,
370    ) -> c::Result_Box<IdentityConfig>;
371
372    pub fn ditto_identity_config_make_offline_playground(
373        app_id: char_p::Ref<'_>,
374        site_id: c_ulonglong,
375    ) -> c::Result_Box<IdentityConfig>;
376
377    pub fn ditto_identity_config_make_online_playground(
378        app_id: char_p::Ref<'_>,
379        shared_token: char_p::Ref<'_>,
380        base_url: char_p::Ref<'_>,
381    ) -> c::Result_Box<IdentityConfig>;
382
383    pub fn ditto_identity_config_make_shared_key(
384        app_id: char_p::Ref<'_>,
385        key_der_b64: char_p::Ref<'_>,
386        site_id: c_ulonglong,
387    ) -> c::Result_Box<IdentityConfig>;
388
389    pub fn ditto_identity_config_make_manual(
390        manual_identity_str: char_p::Ref<'_>,
391    ) -> c::Result_Box<IdentityConfig>;
392
393    pub fn ditto_identity_config_make_manual_v0(
394        config_cbor_b64: char_p::Ref<'_>,
395    ) -> c::Result_Box<IdentityConfig>;
396
397    pub fn ditto_auth_set_login_provider(
398        ditto: &'_ Ditto,
399        login_provider: Option<c::Box<LoginProvider>>,
400    );
401
402    pub fn ditto_auth_client_get_site_id(ditto: &'_ Ditto) -> c_ulonglong;
403
404    pub fn ditto_auth_client_get_app_id(ditto: &'_ Ditto) -> char_p::Box;
405
406    pub fn ditto_auth_client_user_id(ditto: &'_ Ditto) -> Option<char_p::Box>;
407
408    pub unsafe fn ditto_auth_client_make_login_provider(
409        ctx: *mut c_void,
410        retain: Option<unsafe extern "C" fn(*mut c_void)>,
411        release: Option<unsafe extern "C" fn(*mut c_void)>,
412        expiring_cb: unsafe extern "C" fn(*mut c_void, c_uint),
413    ) -> c::Box<LoginProvider>;
414
415    pub fn ditto_auth_client_is_web_valid(ditto: &'_ Ditto) -> c_int;
416
417    pub type FfiConnectionRequest: Send + Sync;
418    #[drop(to impl FfiDropBox for FfiConnectionRequest)]
419    pub fn dittoffi_connection_request_free(__: c::Box<FfiConnectionRequest>);
420
421    pub fn dittoffi_connection_request_peer_metadata_json(
422        r: &FfiConnectionRequest,
423    ) -> c_slice::Ref<'_, u8>;
424
425    pub fn dittoffi_connection_request_identity_service_metadata_json(
426        r: &FfiConnectionRequest,
427    ) -> c_slice::Ref<'_, u8>;
428
429    pub fn dittoffi_connection_request_peer_key_string(r: &FfiConnectionRequest) -> char_p::Box;
430
431    pub fn dittoffi_connection_request_authorize(
432        r: &FfiConnectionRequest,
433        authorized: ConnectionRequestAuthorization,
434    );
435
436    pub fn dittoffi_connection_request_connection_type(r: &FfiConnectionRequest) -> ConnectionType;
437
438    pub fn dittoffi_presence_peer_metadata_json(ditto: &'_ Ditto) -> c_slice::Box<u8>;
439
440    pub fn ditto_auth_client_login_with_credentials(
441        ditto: &'_ Ditto,
442        username: char_p::Ref<'_>,
443        password: char_p::Ref<'_>,
444        provider: char_p::Ref<'_>,
445    ) -> c_int;
446
447    pub fn ditto_auth_client_login_with_token_and_feedback(
448        ditto: &'_ Ditto,
449        token: char_p::Ref<'_>,
450        provider: char_p::Ref<'_>,
451    ) -> c::Result_OptionBoxedCharPtr;
452
453    pub fn ditto_auth_client_login_with_token(
454        ditto: &'_ Ditto,
455        token: char_p::Ref<'_>,
456        provider: char_p::Ref<'_>,
457    ) -> c_int;
458
459    pub fn ditto_auth_client_logout(ditto: &'_ Ditto) -> c_int;
460
461    pub type LoginProvider: Send + Sync;
462    #[drop(to impl FfiDropBox for LoginProvider)]
463    pub fn ditto_auth_login_provider_free(login_provider: c::Box<LoginProvider>);
464
465    pub fn ditto_insert_timeseries_event(
466        ditto: &'_ Ditto,
467        timestamp: [u8; 8], // a u64 ... but arm32
468        nanos: u32,
469        ts_name: char_p::Ref<'_>,
470        cbor: c_slice::Ref<'_, u8>,
471        txn: Option<&'_ mut CWriteTransaction>,
472    ) -> c_int;
473
474    pub fn ditto_set_device_name(ditto: &'_ Ditto, device_name: char_p::Ref<'_>) -> char_p::Box;
475
476    pub unsafe fn ditto_register_presence_v2_callback(
477        ditto: &'_ Ditto,
478        ctx: *mut c_void,
479        retain: Option<unsafe extern "C" fn(*mut c_void)>,
480        release: Option<unsafe extern "C" fn(*mut c_void)>,
481        c_cb: Option<unsafe extern "C" fn(*mut c_void, json: char_p::Ref<'_>)>,
482    );
483
484    pub fn ditto_presence_v2(ditto: &'_ Ditto) -> char_p::Box;
485
486    pub unsafe fn ditto_register_presence_callback_v3(
487        ditto: &'_ Ditto,
488        ctx: *mut c_void,
489        retain: Option<unsafe extern "C" fn(*mut c_void)>,
490        release: Option<unsafe extern "C" fn(*mut c_void)>,
491        c_cb: Option<unsafe extern "C" fn(*mut c_void, json: char_p::Ref<'_>)>,
492    );
493
494    pub fn ditto_presence_v3(ditto: &'_ Ditto) -> char_p::Box;
495
496    pub type DiskUsageObserver: Send + Sync;
497    #[drop(to impl FfiDropBox for DiskUsageObserver)]
498    pub fn ditto_release_disk_usage_callback(_handle: c::Box<DiskUsageObserver>);
499
500    pub unsafe fn ditto_register_disk_usage_callback(
501        ditto: &'_ Ditto,
502        component: FsComponent,
503        ctx: *mut c_void,
504        retain: Option<unsafe extern "C" fn(*mut c_void)>,
505        release: Option<unsafe extern "C" fn(*mut c_void)>,
506        c_cb: Option<unsafe extern "C" fn(*mut c_void, cbor: c_slice::Ref<'_, u8>)>,
507    ) -> Option<c::Box<DiskUsageObserver>>;
508
509    pub fn ditto_disk_usage(ditto: &'_ Ditto, path: FsComponent) -> c_slice::Box<u8>;
510
511    pub type FfiQueryResultItem: Send + Sync;
512    pub fn dittoffi_query_result_item_cbor(_dql_result: &'_ FfiQueryResultItem)
513        -> c_slice::Box<u8>;
514    pub fn dittoffi_query_result_item_json(_dql_result: &'_ FfiQueryResultItem) -> char_p::Box;
515    pub fn dittoffi_query_result_item_new(
516        cbor: c_slice::Ref<'_, u8>,
517    ) -> FfiResult<c::Arc<FfiQueryResultItem>>;
518    #[drop(to impl FfiDropArc for FfiQueryResultItem)]
519    pub fn dittoffi_query_result_item_free(_dql_result: c::Arc<FfiQueryResultItem>);
520
521    pub type FfiQueryResult: Send + Sync;
522    pub fn dittoffi_query_result_item_count(response: &'_ FfiQueryResult) -> usize;
523    pub fn dittoffi_query_result_item_at(
524        response: &'_ FfiQueryResult,
525        index: usize,
526    ) -> c::Arc<FfiQueryResultItem>;
527    pub fn dittoffi_query_result_mutated_document_id_count(response: &'_ FfiQueryResult) -> usize;
528    pub fn dittoffi_query_result_mutated_document_id_at(
529        response: &'_ FfiQueryResult,
530        index: usize,
531    ) -> c_slice::Box<u8>;
532    pub fn dittoffi_query_result_has_commit_id(response: &'_ FfiQueryResult) -> bool;
533    pub fn dittoffi_query_result_commit_id(response: &'_ FfiQueryResult) -> u64;
534    #[drop(to impl FfiDropBox for FfiQueryResult)]
535    pub fn dittoffi_query_result_free(_dql_reponse: c::Box<FfiQueryResult>);
536
537    pub type FfiDiffer: Send + Sync;
538    pub fn dittoffi_differ_new() -> c::Box<FfiDiffer>;
539    pub fn dittoffi_differ_new_with_identity_key_paths_throws<'a>(
540        identity_key_paths: c_slice::Ref<'a, char_p::Ref<'a>>,
541    ) -> FfiResult<c::Box<FfiDiffer>>;
542    #[drop(to impl FfiDropBox for FfiDiffer)]
543    pub fn dittoffi_differ_free(differ: c::Box<FfiDiffer>);
544    pub fn dittoffi_differ_diff(
545        differ: &'_ FfiDiffer,
546        items: c_slice::Ref<'_, c::Arc<FfiQueryResultItem>>,
547    ) -> FfiCborData;
548    pub fn dittoffi_differ_identity_key_path_count(differ: &'_ FfiDiffer) -> usize;
549    pub fn dittoffi_differ_identity_key_path_at(differ: &'_ FfiDiffer, idx: usize) -> char_p::Box;
550
551    pub fn dittoffi_try_exec_statement(
552        ditto: &'_ Ditto,
553        query: char_p::Ref<'_>,
554        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
555    ) -> c::FfiResultBox<FfiQueryResult>;
556
557    pub unsafe fn dittoffi_try_experimental_register_change_observer_str(
558        ditto: &'_ Ditto,
559        query: char_p::Ref<'_>,
560        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
561        lq_availability: LiveQueryAvailability,
562        ctx: *mut c_void,
563        retain: Option<unsafe extern "C" fn(*mut c_void)>,
564        release: Option<unsafe extern "C" fn(*mut c_void)>,
565        c_cb: unsafe extern "C" fn(ctx: *mut c_void, params: ChangeHandlerWithQueryResult),
566    ) -> c::Result<i64>;
567
568    pub fn dittoffi_try_add_sync_subscription(
569        ditto: &'_ Ditto,
570        query: char_p::Ref<'_>,
571        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
572    ) -> c::FfiResult<()>;
573
574    pub fn dittoffi_try_remove_sync_subscription(
575        ditto: &'_ Ditto,
576        query: char_p::Ref<'_>,
577        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
578    ) -> c::FfiResult<()>;
579
580    pub fn ditto_small_peer_info_get_is_enabled(ditto: &'_ Ditto) -> bool;
581    pub fn ditto_small_peer_info_set_enabled(ditto: &'_ Ditto, enabled: bool);
582
583    pub fn ditto_small_peer_info_get_sync_scope(ditto: &'_ Ditto) -> DittoSmallPeerInfoSyncScope;
584    pub fn ditto_small_peer_info_set_sync_scope(
585        ditto: &'_ Ditto,
586        sync_scope: DittoSmallPeerInfoSyncScope,
587    );
588
589    pub fn ditto_small_peer_info_get_metadata(ditto: &'_ Ditto) -> char_p::Box;
590    pub fn ditto_small_peer_info_set_metadata(ditto: &'_ Ditto, metadata: char_p::Ref<'_>) -> i32;
591
592    pub fn dittoffi_logger_try_export_to_file_async(
593        dest_path: char_p::Ref<'_>,
594        completion: BoxDynFnMut1<(), FfiResult<u64>>,
595    );
596
597    pub fn dittoffi_ditto_try_set_transport_config(
598        ditto: &'_ Ditto,
599        transport_config: c_slice::Ref<'_, u8>,
600        should_validate: bool,
601    ) -> c::FfiResult<()>;
602
603    pub fn dittoffi_ditto_try_start_sync(ditto: &'_ Ditto) -> c::FfiResult<()>;
604    pub fn dittoffi_ditto_stop_sync(ditto: &'_ Ditto);
605    pub fn dittoffi_ditto_is_sync_active(ditto: &'_ Ditto) -> bool;
606    pub fn dittoffi_ditto_transport_config(ditto: &'_ Ditto) -> c_slice::Box<u8>;
607
608    pub fn dittoffi_ditto_set_cloud_sync_enabled(ditto: &'_ Ditto, enabled: bool);
609    pub fn dittoffi_ditto_is_activated(ditto: &'_ Ditto) -> bool;
610
611    // === DQL Transactions ===
612
613}
614
615// Sync Subscriptions API
616#[apply(extern_type_polyfill!)]
617unsafe extern "C" {
618    pub type FfiSyncSubscription: Send + Sync;
619    #[drop(to impl FfiDropBox for FfiSyncSubscription)]
620    pub fn dittoffi_sync_subscription_free(subscription: c::Box<FfiSyncSubscription>);
621    pub fn dittoffi_sync_subscriptions_free_sparse(vec: c::Vec<c::Box<FfiSyncSubscription>>);
622    pub fn dittoffi_sync_register_subscription_throws(
623        ditto: &'_ Ditto,
624        query: char_p::Ref<'_>,
625        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
626    ) -> c::FfiResult<c::Box<FfiSyncSubscription>>;
627    pub fn dittoffi_sync_subscriptions(ditto: &'_ Ditto) -> c::Vec<c::Box<FfiSyncSubscription>>;
628    pub fn dittoffi_sync_subscription_id(handle: &FfiSyncSubscription) -> c_slice::Box<u8>;
629    pub fn dittoffi_sync_subscription_cancel(handle: &FfiSyncSubscription);
630    pub fn dittoffi_sync_subscription_is_cancelled(handle: &FfiSyncSubscription) -> bool;
631    pub fn dittoffi_sync_subscription_query_string(handle: &FfiSyncSubscription) -> char_p::Box;
632    pub fn dittoffi_sync_subscription_query_arguments(
633        handle: &FfiSyncSubscription,
634    ) -> Option<c_slice::Box<u8>>;
635}
636
637pub type FfiStore = Ditto;
638pub type FfiDynSignalNext = dyn 'static + Send + Sync + Fn();
639
640pub type FfiDynChangeHandlerWithSignalNext =
641    dyn 'static + Send + FnMut(repr_c::Box<FfiQueryResult>, repr_c::Arc<FfiDynSignalNext>);
642
643// Store Observer API
644#[apply(extern_type_polyfill!)]
645unsafe extern "C" {
646    pub type FfiStoreObserver: Send + Sync;
647    #[drop(to impl FfiDropBox for FfiStoreObserver)]
648    pub fn dittoffi_store_observer_free(handle: c::Box<FfiStoreObserver>);
649    pub fn dittoffi_store_observer_free_sparse(vec: c::Vec<c::Box<FfiStoreObserver>>);
650    pub fn dittoffi_store_register_observer_throws(
651        ditto: &'_ Ditto,
652        query: char_p::Ref<'_>,
653        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
654        callback: repr_c::Box<FfiDynChangeHandlerWithSignalNext>,
655    ) -> FfiResult<c::Box<FfiStoreObserver>>;
656    pub fn dittoffi_store_observers(store: &'_ FfiStore) -> c::Vec<c::Box<FfiStoreObserver>>;
657    pub fn dittoffi_store_observer_id(handle: &FfiStoreObserver) -> c_slice::Box<u8>;
658    pub fn dittoffi_store_observer_cancel(handle: &FfiStoreObserver);
659    pub fn dittoffi_store_observer_is_cancelled(handle: &FfiStoreObserver) -> bool;
660    pub fn dittoffi_store_observer_query_string(handle: &FfiStoreObserver) -> char_p::Box;
661    pub fn dittoffi_store_observer_query_arguments(
662        handle: &FfiStoreObserver,
663    ) -> Option<c_slice::Box<u8>>;
664}
665
666// DQL Transactions API
667#[apply(extern_type_polyfill)]
668unsafe extern "C" {
669    pub type FfiTransaction: Send + Sync;
670    #[drop(to impl FfiDropBox for FfiTransaction)]
671    pub fn dittoffi_transaction_free(transaction: c::Box<FfiTransaction>);
672    pub fn dittoffi_store_begin_transaction_async_throws(
673        store: &'_ FfiStore,
674        options: BeginTransactionOptions<'_>,
675        continuation: BoxDynFnMut1<(), FfiResult<c::Box<FfiTransaction>>>,
676    );
677    pub fn dittoffi_transaction_complete_async_throws(
678        transaction: &'_ FfiTransaction,
679        action: TransactionCompletionAction,
680        continuation: BoxDynFnMut1<(), FfiResult<TransactionCompletionAction>>,
681    );
682    pub fn dittoffi_transaction_execute_async_throws(
683        transaction: &'_ FfiTransaction,
684        query: char_p::Ref<'_>,
685        query_args: Option<c_slice::Ref<'_, u8>>,
686        continuation: BoxDynFnMut1<(), c::FfiResultBox<FfiQueryResult>>,
687    );
688    pub fn dittoffi_transaction_info(transaction: &'_ FfiTransaction) -> FfiCborData;
689}
690
691pub type FfiDynPresenceCallback = dyn 'static + Send + FnMut(c_slice::Box<u8>);
692
693// Presence API (uses Presence v3 format)
694#[apply(extern_type_polyfill)]
695unsafe extern "C" {
696    pub type FfiPresenceObserver: Send + Sync;
697    #[drop(to impl FfiDropBox for FfiPresenceObserver)]
698    pub fn dittoffi_presence_observer_free(observer: repr_c::Box<FfiPresenceObserver>);
699    pub fn dittoffi_presence_register_observer_throws(
700        ditto: &'_ Ditto,
701        callback: repr_c::Box<FfiDynPresenceCallback>,
702    ) -> FfiResult<repr_c::Box<FfiPresenceObserver>>;
703    pub fn dittoffi_presence_observer_id(observer: &FfiPresenceObserver) -> c_slice::Box<u8>;
704    pub fn dittoffi_presence_observer_cancel(observer: &FfiPresenceObserver);
705    pub fn dittoffi_presence_observer_is_cancelled(observer: &FfiPresenceObserver) -> bool;
706    pub fn dittoffi_presence_graph(ditto: &'_ Ditto) -> c_slice::Box<u8>;
707
708    pub fn dittoffi_presence_peer_metadata(ditto: &'_ Ditto) -> char_p::Box;
709    pub fn dittoffi_presence_set_peer_metadata_json_throws(
710        ditto: &'_ Ditto,
711        peer_info: c_slice::Ref<'_, u8>,
712    ) -> FfiResult<()>;
713
714    // TODO(v5): remove
715    #[allow(deprecated)]
716    #[deprecated(note = "Use `dittoffi_presence_set_peer_metadata_json_throws` instead")]
717    pub fn dittoffi_presence_try_set_peer_metadata_json(
718        ditto: &'_ Ditto,
719        peer_info: c_slice::Ref<'_, u8>,
720    ) -> FfiResult<()>;
721
722    pub fn dittoffi_presence_set_connection_request_handler(
723        ditto: &'_ Ditto,
724        ffi_handler: Option<
725            safer_ffi::dyn_traits::VirtualPtr<dyn Send + Sync + FfiConnectionRequestHandler>,
726        >,
727    );
728}
729
730impl fmt::Debug for Ditto {
731    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
732        f.debug_struct("Ditto").finish()
733    }
734}
735
736impl FfiDropBox for IdentityConfig {
737    unsafe fn drop_boxed(_: &mut c::Box<Self>) {
738        // We don't expose this functionality in the API, since it is to be
739        // given to the final `Ditto` constructor anyway
740        panic!("A `c::Box<IdentityConfig>` is to be fed to `ditto_make`")
741    }
742}
743
744#[repr(C)]
745pub enum ConnectionRequestAuthorization {
746    Deny,
747
748    Allow,
749}
750
751#[non_exhaustive]
752#[repr(C)]
753#[derive(Debug, Clone, PartialEq, Eq)]
754pub enum Platform {
755    Windows,
756    Mac,
757    Ios,
758    Tvos,
759    Android,
760    Linux,
761    Unknown,
762}
763
764#[::safer_ffi::derive_ReprC]
765#[repr(C)]
766pub struct FfiResult<T: ::safer_ffi::layout::ReprC> {
767    pub error: Option<c::Box<FfiError>>,
768    pub success: T::CLayout,
769}
770
771impl fmt::Debug for FfiError {
772    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
773        f.debug_struct("FfiError").finish()
774    }
775}
776
777// These are needed because `FfiResult` stores a `T::CLayout` rather than a `T`. For opaque types
778// (such as `FfiTransaction`), this is a `*mut u8`, which doesn't implement `Send` or `Sync`.
779//
780// But this `!Send`-ness and `!Sync`-ness is not 100% "real", in a sense. There's nothing about a
781// `*mut u8` that prevents it being sent across threads - rather it's a design decision to force
782// people who are likely writing unsafe code to think about whether their `*mut T`-containing
783// struct should implement `Send` or `Sync`
784//
785// In our case, this is overly cautious, so we provide blanket impls for `FfiResult<T>`
786unsafe impl<T: ::safer_ffi::layout::ReprC> Send for FfiResult<T> where T: Send {}
787unsafe impl<T: ::safer_ffi::layout::ReprC> Sync for FfiResult<T> where T: Sync {}
788
789// Hack: we use a temporary rename as `CoreApiErrorKind`
790// so that rustdoc shows the associated items under that name.
791pub use CoreApiErrorKind as FfiErrorCode;
792#[apply(crate::ffi_utils::non_exhaustive_ffi_enum!)]
793#[repr(i32)]
794#[derive(Clone, Copy, PartialEq, Eq)]
795pub enum CoreApiErrorKind {
796    // Note(Daniel): keep up-to-date with `ffi/src/result/error.rs`!
797    ActivationLicenseTokenExpired,
798    ActivationLicenseTokenInvalid,
799    ActivationLicenseUnsupportedFutureVersion,
800    ActivationNotActivated,
801    ActivationUnnecessary,
802    AuthenticationExpirationHandlerMissing,
803    Base64Invalid,
804    CborInvalid,
805    CborUnsupported,
806    Crdt,
807    DifferIdentityKeyPathInvalid,
808    DqlEvaluationError,
809    DqlInvalidQueryArgs,
810    DqlQueryCompilation,
811    DqlUnsupported,
812    EncryptionExtraneousPassphraseGiven,
813    EncryptionPassphraseInvalid,
814    EncryptionPassphraseNotGiven,
815    JsFloatingStoreOperation,
816    IoAlreadyExists,
817    IoNotFound,
818    IoOperationFailed,
819    IoPermissionDenied,
820    LockedDittoWorkingDirectory,
821    ParameterQuery,
822    StoreDatabase,
823    StoreDocumentId,
824    StoreDocumentNotFound,
825    StoreQuery,
826    StoreTransactionReadOnly,
827    Transport,
828    Unsupported,
829    ValidationDepthLimitExceeded,
830    ValidationInvalidCbor,
831    ValidationInvalidJson,
832    ValidationInvalidTransportConfig,
833    ValidationInvalidDittoConfig,
834    ValidationNotAMap,
835    ValidationSizeLimitExceeded,
836    Unknown,
837    Internal,
838    // _NonExhaustive /* handled properly by `non_exhaustive_ffi_enum!` */
839}
840
841// Keep in sync with ffi/src/presence.rs (and core/presence/src/types.rs)
842crate::ffi_utils::non_exhaustive_ffi_enum! {
843    #[repr(i32)]
844    #[derive(Clone, PartialEq, Eq)]
845    pub enum ConnectionType {
846        Bluetooth,
847        AccessPoint,
848        P2PWiFi,
849        WebSocket,
850    }
851}
852
853#[repr(C)]
854#[derive(Debug, Clone, PartialEq, Eq)]
855pub enum DittoErrorCode {
856    Ok = 0x0000000,
857    Unknown = 0x0000001,
858    NotImplemented = 0x0000002,
859    // global ditto errors =    0x1000000,
860    FailedToAcquireLockFile = 0x1000001,
861    // Encryption errors =      0x2000000,
862    InvalidPassphrase = 0x2000001,
863    ExtraneousPassphraseGiven = 0x2000002,
864    PassphraseNotGiven = 0x2000003,
865    AlreadyEncrypted = 0x2000004,
866    EncryptionFailed = 0x2000005,
867    CannotBeEncrypted = 0x2000006,
868    NotInitialized = 0x2000007,
869}
870
871#[non_exhaustive]
872#[repr(C)]
873#[derive(Debug, Clone, PartialEq, Eq)]
874#[allow(dead_code)]
875pub enum Language {
876    Swift,
877    ObjectiveC,
878    CPlusPlus,
879    CSharp,
880    Javascript,
881    Unknown,
882    Rust,
883}
884
885#[repr(C)]
886#[derive(Copy, Clone, Debug, PartialEq, Eq)]
887pub enum CLogLevel {
888    // Starts at 1 to match the Rust log levels which have an `Off` case with
889    // value 0
890    Error = 1,
891    Warning,
892    Info,
893    Debug,
894    Verbose,
895}
896
897#[repr(C)]
898#[derive(Debug, Clone, Copy, PartialEq, Eq)]
899pub enum HistoryTracking {
900    Enabled,
901    Disabled,
902}
903
904#[repr(C)]
905#[derive(Copy, Clone, Debug, PartialEq)]
906#[allow(dead_code)]
907pub enum LicenseVerificationResult {
908    LicenseOk = 0,
909    VerificationFailed = -1,
910    LicenseExpired = -2,
911    UnsupportedFutureVersion = -3,
912}
913
914#[repr(C)]
915#[derive(Copy, Clone, Debug, PartialEq, Eq)]
916pub enum WriteStrategyRs {
917    Merge,
918    InsertIfAbsent,
919    InsertDefaultIfAbsent,
920}
921
922#[repr(C)]
923#[derive(Copy, Clone, Debug, PartialEq, Eq)]
924pub enum FsComponent {
925    Root = 0,
926    Store,
927    Auth,
928    Replication,
929    Attachment,
930}
931
932#[derive(Debug, Clone)]
933#[repr(C)]
934pub struct COrderByParam<'query> {
935    pub query_c_str: char_p::Ref<'query>,
936    pub direction: QuerySortDirection,
937}
938impl NonOpaque for COrderByParam<'_> {}
939
940#[derive(Clone, Debug, PartialEq)]
941#[derive_ReprC(js, rename = "dittoffi_transaction_options")]
942#[repr(C)]
943pub struct FfiTransactionOptions {
944    /// Whether the transaction is read-only.
945    pub is_read_only: bool,
946
947    /// An optional hint for the transaction. This is often useful for identifying a transaction in
948    /// logs.
949    pub hint: Option<char_p::Box>,
950}
951
952/// FFI appropriate representation of the options available when beginning a transaction.
953#[derive(Clone, Debug, Default, PartialEq)]
954#[derive_ReprC(js, rename = "dittoffi_store_begin_transaction_options")]
955#[repr(C)]
956pub struct BeginTransactionOptions<'hint> {
957    /// Whether the transaction is read-only. Defaults to `false`.
958    pub is_read_only: bool,
959
960    /// An optional hint for the transaction. This is often useful for identifying a transaction in
961    /// logs.
962    pub hint: Option<char_p::Ref<'hint>>,
963}
964
965// inner module to reduce scope of `#[allow(deprecated)]` (required for saferffi c-style enums)
966pub use transaction_completion::*;
967#[allow(deprecated)]
968mod transaction_completion {
969    #[derive(Debug, Clone, Copy)]
970    #[repr(C)]
971    #[::safer_ffi::derive_ReprC]
972    pub enum TransactionCompletionAction {
973        Commit = 0,
974        Rollback = 1,
975    }
976}
977
978#[derive_ReprC(js, rename = "dittoffi_cbor_data")]
979#[repr(transparent)]
980// TODO(cameron): is this the same?
981pub struct FfiCborData(pub c_slice::Box<u8>);
982
983#[repr(C)]
984#[derive(Copy, Clone, Debug, PartialEq, Eq)]
985#[allow(dead_code)]
986pub enum QuerySortDirection {
987    Ascending = 1,
988    Descending,
989}
990
991#[repr(C)]
992#[derive(Debug, Clone, Copy, PartialEq, Eq)]
993pub enum DittoCrdtType {
994    Counter = 0,
995    Register = 1,
996    Attachment = 2,
997    Rga = 3,
998    RWMap = 4,
999}
1000
1001#[repr(C)]
1002#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
1003pub enum PathAccessorType {
1004    String,
1005    Number,
1006    Int,
1007    UInt,
1008    Float,
1009    Double,
1010    Bool,
1011    Null,
1012    Object,
1013    Array,
1014    Any,
1015
1016    // CRDT types
1017    Counter,
1018    Register,
1019    Attachment,
1020    // This isn't ever used as things stand, but is here for completeness and to
1021    // make things easier in future if we do want to support it
1022    RWMap,
1023}
1024
1025impl fmt::Debug for Document {
1026    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1027        let c_str = ditto_document_id(self);
1028        // TODO: FIXME
1029        f.debug_struct("Document").field("id", &c_str).finish()
1030    }
1031}
1032
1033#[repr(C)]
1034#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1035#[allow(dead_code)]
1036pub enum LiveQueryAvailability {
1037    Always,
1038    WhenSignalled,
1039}
1040
1041#[repr(C)]
1042#[allow(nonstandard_style)]
1043pub struct ChangeHandlerWithDocsDiff {
1044    /// The vec must be freed with `ditto_sparse_vec_documents_free`. The `Document`s contained by
1045    /// the vec are owned by the recipient of the diff and should be freed independently of the
1046    /// vec.
1047    pub documents: c::Vec<c::Box<Document>>,
1048    pub is_initial: bool,
1049    /// The vec, if present, must be freed with `ditto_sparse_vec_documents_free`. The `Document`s
1050    /// contained by the vec are owned by the recipient of the diff and should be freed
1051    /// independently of the vec.
1052    pub old_documents: Option<c::Vec<c::Box<Document>>>,
1053    /// Must be freed using `ditto_free_indices`.
1054    pub insertions: Option<c_slice::Box<usize>>,
1055    /// Must be freed using `ditto_free_indices`.
1056    pub deletions: Option<c_slice::Box<usize>>,
1057    /// Must be freed using `ditto_free_indices`.
1058    pub updates: Option<c_slice::Box<usize>>,
1059    /// Must be freed using `ditto_free_indices`.
1060    pub moves: Option<c_slice::Box<usize>>,
1061}
1062
1063#[repr(C)]
1064#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1065#[allow(dead_code)]
1066pub enum AttachmentFileOperation {
1067    Copy = 1,
1068    Move,
1069}
1070
1071#[repr(C)]
1072pub struct Attachment {
1073    pub id: c_slice::Box<u8>,
1074    pub len: u64,
1075    pub handle: c::Box<AttachmentHandle>,
1076}
1077
1078impl fmt::Debug for AttachmentHandle {
1079    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1080        f.debug_struct("AttachmentHandle").finish()
1081    }
1082}
1083
1084#[repr(C)]
1085#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1086pub enum StringPrimitiveFormat {
1087    WithQuotes,
1088    WithoutQuotes,
1089}
1090
1091#[repr(C)]
1092#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1093/// Which peers to replicate the `__small_peer_info` collection to.
1094pub enum DittoSmallPeerInfoSyncScope {
1095    BigPeerOnly,
1096    LocalPeerOnly,
1097}
1098
1099pub trait IntoRustResult {
1100    type Ok;
1101
1102    fn into_rust_result(_: Self) -> Result<Self::Ok, ::core::num::NonZeroI32>;
1103}
1104
1105#[derive_ReprC]
1106#[repr(C)]
1107pub struct ChangeHandlerWithQueryResult {
1108    /// Must be freed with `dittoffi_query_result_free`.
1109    pub query_result: c::Box<FfiQueryResult>,
1110}
1111
1112#[derive_ReprC(dyn)]
1113pub trait FfiFnMut {
1114    fn call(&mut self);
1115}
1116
1117impl<F: FnMut()> FfiFnMut for F {
1118    fn call(&mut self) {
1119        self()
1120    }
1121}
1122
1123// Note(Daniel): keep up-to-date with `ffi/src/auth/mod.rs`
1124#[derive_ReprC(dyn, Clone)]
1125pub trait FfiConnectionRequestHandler: 'static + Send + Sync {
1126    fn on_connecting(&self, connection_request: c::Box<FfiConnectionRequest>);
1127}
1128
1129impl<F> FfiConnectionRequestHandler for F
1130where
1131    F: 'static + Send + Sync + Fn(c::Box<FfiConnectionRequest>),
1132{
1133    fn on_connecting(&self, connection_request: c::Box<FfiConnectionRequest>) {
1134        self(connection_request)
1135    }
1136}
1137
1138#[repr(C)]
1139#[derive(Copy, Clone, Debug, PartialEq)]
1140// Keep up-to-date with `ffi/src/result/error/transport.rs`
1141pub enum DittoSdkTransportsError {
1142    None = 0,
1143    Generic = 1,
1144    Unavailable = 2,
1145    MissingBluetoothInfoPlistEntry = 3,
1146    MissingBluetoothUIBackgroundModesInfoPlistEntry = 4,
1147}
1148
1149#[cfg(feature = "experimental-bus")]
1150#[apply(extern_type_polyfill!)]
1151unsafe extern "C" {
1152    pub fn dittoffi_get_experimental_bus(ditto: &Ditto) -> ::dittolive_ditto_base::bus::Bus;
1153}