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