dittolive-ditto-sys 4.0.0-beta1

Native bindings to Ditto library
Documentation
//! Manually Generated DittoFFI Bindings
//!
//! These must be updated when dittoffi changes

#![warn(rust_2018_idioms)]
#![allow(clippy::all)]
#![warn(clippy::correctness)]
#![cfg_attr(not(test), warn(clippy::perf))]
#![deny(unsafe_op_in_unsafe_fn)]
#![recursion_limit = "256"]
#![cfg_attr(
    doc,
    warn(
        rustdoc::bare_urls,
        rustdoc::broken_intra_doc_links,
        rustdoc::invalid_codeblock_attributes,
        rustdoc::invalid_rust_codeblocks,
        rustdoc::missing_crate_level_docs,
    )
)]

#[allow(unused_extern_crates)]
extern crate implicit_dittoffi_dependency_hack;

use ::macro_rules_attribute::apply;
use ::std::{
    fmt,
    os::raw::{c_double, c_int, c_uint, c_ulonglong, c_void},
    sync::Arc,
};
use tokio::runtime::{Handle, Runtime};

use self::ffi_utils::{
    c_slice, char_p, extern_type_polyfill, repr_c as c, FfiDrop, NonOpaque, Out,
};

pub mod ffi_utils;

impl fmt::Debug for c::Box<Ditto> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Ditto").finish()
    }
}

impl FfiDrop for c::Box<UninitializedDitto> {
    unsafe fn drop(&mut self) {
        // We don't expose this functionality in the API,
        // since it is to be given to the final `Ditto` constructor anyways
        panic!("A `c::Box<UninitializedDitto>` is to be fed to `ditto_make`")
    }
}

#[non_exhaustive]
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Platform {
    Windows,
    Mac,
    Ios,
    Android,
    Linux,
    Unknown,
}

#[non_exhaustive]
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[allow(dead_code)]
pub enum Language {
    Swift,
    ObjectiveC,
    CPlusPlus,
    CSharp,
    Javascript,
    Unknown,
    Rust,
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CLogLevel {
    // Starts at 1 to match the Rust log levels which have an `Off` case with
    // value 0
    Error = 1,
    Warning,
    Info,
    Debug,
    Verbose,
}

#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WebSocketMode {
    Enabled,
    Disabled,
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HistoryTracking {
    Enabled,
    Disabled,
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(dead_code)]
pub enum LicenseVerificationResult {
    LicenseOk = 0,
    VerificationFailed = -1,
    LicenseExpired = -2,
    UnsupportedFutureVersion = -3,
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum WriteStrategyRs {
    Merge,
    InsertIfAbsent,
    InsertDefaultIfAbsent,
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FsComponent {
    Root = 0,
    Store,
    Auth,
    Replication,
    Attachment,
}

#[repr(C)]
pub struct COrderByParam<'query> {
    pub query_c_str: char_p::Ref<'query>,
    pub direction: QuerySortDirection,
}
impl NonOpaque for COrderByParam<'_> {}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[allow(dead_code)]
pub enum QuerySortDirection {
    Ascending = 1,
    Descending,
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DittoCrdtType {
    Counter = 0,
    Register = 1,
    Attachment = 2,
    Rga = 3,
    RWMap = 4,
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum PathAccessorType {
    String,
    Number,
    Int,
    UInt,
    Float,
    Double,
    Bool,
    Null,
    Object,
    Array,
    Any,

    // CRDT types
    Counter,
    Register,
    Attachment,
    // This isn't ever used as things stand, but is here for completeness and to
    // make things easier in future if we do want to support it
    RWMap,
}

impl fmt::Debug for c::Box<Document> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let c_str = unsafe { ditto_document_id(self) };
        // TODO: FIXME
        f.debug_struct("Document").field("id", &c_str).finish()
    }
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[allow(dead_code)]
pub enum LiveQueryAvailability {
    Always,
    WhenSignalled,
}

#[repr(C)]
#[allow(nonstandard_style)]
pub struct c_cb_params {
    /// Must be freed with `ditto_free_documents`.
    pub documents: c::Vec<c::Box<Document>>,
    pub is_initial: bool,
    /// Must be freed with `ditto_free_documents`.
    pub old_documents: Option<c::Vec<c::Box<Document>>>,
    /// Must be freed using `ditto_free_indices`.
    pub insertions: Option<c_slice::Box<usize>>,
    /// Must be freed using `ditto_free_indices`.
    pub deletions: Option<c_slice::Box<usize>>,
    /// Must be freed using `ditto_free_indices`.
    pub updates: Option<c_slice::Box<usize>>,
    /// Must be freed using `ditto_free_indices`.
    pub moves: Option<c_slice::Box<usize>>,
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[allow(dead_code)]
pub enum AttachmentFileOperation {
    Copy = 1,
    Move,
}

#[repr(C)]
pub struct Attachment {
    pub id: c_slice::Box<u8>,
    pub len: u64,
    pub handle: c::Box<AttachmentHandle>,
}

impl fmt::Debug for c::Box<AttachmentHandle> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("AttachmentHandle").finish()
    }
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum StringPrimitiveFormat {
    WithQuotes,
    WithoutQuotes,
}

#[repr(C)]
pub struct AuthenticationResult {
    pub return_code: c_int,
    pub client_info: Option<safer_ffi::String>,
}

#[apply(extern_type_polyfill!)]
extern "C" {
    // we need to let the build.rs script control the dylib vs. static choice
    pub type Ditto: Send + Sync;
    pub fn ditto_drop(ditto: *mut Ditto);

    pub fn ditto_init_sdk_version(
        platform: Platform,
        language: Language,
        sdk_semver: char_p::Ref<'_>,
    );

    pub type UninitializedDitto;
    pub fn uninitialized_ditto_make(working_dir: char_p::Ref<'_>) -> c::Box<UninitializedDitto>;
    pub fn uninitialized_ditto_make_with_executor(
        working_dir: char_p::Ref<'_>,
        executor: c::Box<Executor>,
    ) -> c::Box<UninitializedDitto>;
    pub fn ditto_make(
        uninit_ditto: c::Box<UninitializedDitto>,
        auth_client: &'_ AuthClient,
        history_tracking: HistoryTracking,
    ) -> c::Box<Ditto>;

    pub fn ditto_logger_init();
    pub fn ditto_logger_enabled(enabled: bool);
    pub fn ditto_logger_enabled_get() -> bool;
    pub fn ditto_logger_emoji_headings_enabled(enabled: bool);
    pub fn ditto_logger_emoji_headings_enabled_get() -> bool;
    pub fn ditto_logger_minimum_log_level_get() -> CLogLevel;
    pub fn ditto_logger_minimum_log_level(log_level: CLogLevel);

    pub fn ditto_shutdown(ditto: &'_ Ditto);
    #[drop]
    pub fn ditto_free(ditto: c::Box<Ditto>);
    pub fn ditto_start_tcp_server(ditto: &'_ Ditto, bind: Option<char_p::Ref<'_>>) -> c_int;
    pub fn ditto_stop_tcp_server(ditto: &'_ Ditto);
    pub fn ditto_start_http_server(
        ditto: &'_ Ditto,
        bind: Option<char_p::Ref<'_>>,
        static_path: Option<char_p::Ref<'_>>,
        enable_websocket: WebSocketMode,
        tls_cert_path: Option<char_p::Ref<'_>>,
        tls_key_path: Option<char_p::Ref<'_>>,
    ) -> c_int;
    pub fn ditto_stop_http_server(ditto: &'_ Ditto);
    pub fn ditto_add_static_tcp_client(
        ditto: &Ditto,
        address: char_p::Ref<'_>,
    ) -> c::Box<StaticTcpClientPlatformHandle>;
    pub fn ditto_add_websocket_client(
        ditto: &'_ Ditto,
        address: char_p::Ref<'_>,
        routing_hint: c_uint,
    ) -> c::Box<WebsocketClientPlatformHandle>;
    pub fn ditto_add_internal_mdns_transport(ditto: &'_ Ditto) -> c::Box<MdnsClientPlatformHandle>;
    pub fn ditto_add_internal_mdns_advertiser(ditto: &'_ Ditto)
        -> c::Box<MdnsServerPlatformHandle>;
    pub fn ditto_add_internal_ble_client_transport(
        ditto: &'_ Ditto,
    ) -> c::Box<BleClientPlatformHandle>;
    pub fn ditto_add_internal_ble_server_transport(
        ditto: &'_ Ditto,
    ) -> c::Box<BleServerPlatformHandle>;
    pub fn ditto_add_multicast_transport(ditt: &'_ Ditto);
    pub fn ditto_remove_multicast_transport(ditt: &'_ Ditto);
    pub fn ditto_get_sdk_version() -> char_p::Box;
    pub fn verify_license(
        license: char_p::Ref<'_>,
        out_err_msg: Option<Out<'_, Option<char_p::Box>>>,
    ) -> LicenseVerificationResult;
    pub fn ditto_run_garbage_collection(ditto: &'_ Ditto);
    pub fn ditto_disable_sync_with_v3(ditto: &'_ Ditto) -> c_int;

    pub fn ditto_get_collection_names(ditto: &'_ Ditto) -> c::Result_Vec<char_p::Box>;

    pub fn ditto_queries_hash<'s, 'l: 's>(
        ditto: &Ditto,
        coll_names: c_slice::Ref<'s, char_p::Ref<'l>>,
        queries: c_slice::Ref<'s, char_p::Ref<'l>>,
    ) -> c::Result<u64>;

    pub fn ditto_queries_hash_mnemonic<'s, 'l: 's>(
        ditto: &'_ Ditto,
        coll_names: c_slice::Ref<'s, char_p::Ref<'l>>,
        queries: c_slice::Ref<'s, char_p::Ref<'l>>,
    ) -> c::Result<Option<char_p::Box>>;

    pub fn ditto_collection(ditto: &'_ Ditto, name: char_p::Ref<'_>) -> c_int;

    pub fn ditto_collection_insert_value(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        doc_cbor: c_slice::Ref<'_, u8>,
        doc_id: Option<c_slice::Ref<'_, u8>>,
        write_strategy: WriteStrategyRs,
        txn: Option<&'_ mut CWriteTransaction>,
    ) -> c::Result_BoxedSlice<u8>;

    pub fn ditto_collection_update(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        transaction: &'_ mut CWriteTransaction,
        document: c::Box<Document>,
    ) -> c_int;

    pub fn ditto_collection_evict(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        transaction: &'_ mut CWriteTransaction,
        id: c_slice::Ref<'_, u8>,
    ) -> c::Result<bool>;

    pub fn ditto_collection_remove(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        transaction: &'_ mut CWriteTransaction,
        id: c_slice::Ref<'_, u8>,
    ) -> c::Result<bool>;

    pub fn ditto_collection_get(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        id: c_slice::Ref<'_, u8>,
        transaction: &'_ mut CReadTransaction,
    ) -> c::Result_Box<Document>;

    pub fn ditto_collection_exec_query_str<'order_ref, 'order: 'order_ref>(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        txn: Option<&'_ mut CWriteTransaction>,
        query: char_p::Ref<'_>,
        query_args: Option<c_slice::Ref<'_, u8>>,
        order_by_params: c_slice::Ref<'order_ref, COrderByParam<'order>>,
        limit: c_int,
        offset: c_uint,
    ) -> c::Result_Vec<c::Box<Document>>;

    pub fn ditto_collection_remove_query_str<'order_ref, 'order: 'order_ref>(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        transaction: &'_ mut CWriteTransaction,
        query: char_p::Ref<'_>,
        query_args: Option<c_slice::Ref<'_, u8>>,
        order_by_params: c_slice::Ref<'order_ref, COrderByParam<'order>>,
        limit: c_int,
        offset: c_uint,
    ) -> c::Result_Vec<c_slice::Box<u8>>;

    pub fn ditto_collection_evict_query_str<'order_ref, 'order: 'order_ref>(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        transaction: &'_ mut CWriteTransaction,
        query: char_p::Ref<'_>,
        query_args: Option<c_slice::Ref<'_, u8>>,
        order_by_params: c_slice::Ref<'order_ref, COrderByParam<'order>>,
        limit: c_int,
        offset: c_uint,
    ) -> c::Result_Vec<c_slice::Box<u8>>;

    pub fn ditto_read_transaction<'txn>(ditto: &'_ Ditto) -> c::Result_Box<CReadTransaction>;

    pub type CReadTransaction;
    #[drop]
    pub fn ditto_read_transaction_free(transaction: c::Box<CReadTransaction>);

    pub fn ditto_write_transaction(ditto: &'_ Ditto) -> c::Result_Box<CWriteTransaction>;

    pub type CWriteTransaction;
    #[drop]
    pub fn ditto_write_transaction_free(txn: c::Box<CWriteTransaction>);

    pub fn ditto_write_transaction_commit(
        ditto: &Ditto,
        transaction: c::Box<CWriteTransaction>,
    ) -> c_int;

    pub fn ditto_write_transaction_rollback(ditto: &Ditto, transaction: c::Box<CWriteTransaction>);

    pub fn ditto_document_id(document: &'_ Document) -> c_slice::Box<u8>;

    pub fn ditto_document_id_query_compatible(
        id: c_slice::Ref<'_, u8>,
        string_primitive_format: StringPrimitiveFormat,
    ) -> char_p::Box;

    pub fn ditto_validate_document_id(
        cbor: c_slice::Ref<'_, u8>,
        out_cbor: Out<'_, Option<c_slice::Box<u8>>>,
    ) -> c_uint;

    pub fn ditto_add_subscription<'s, 'l: 's>(
        ditto: &'_ Ditto,
        collection: char_p::Ref<'_>,
        query: char_p::Ref<'_>,
        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
        order_by: c_slice::Ref<'s, COrderByParam<'l>>,
        limit: c_int,
        offset: c_uint,
    ) -> c_int;

    pub fn ditto_remove_subscription<'s, 'l: 's>(
        ditto: &'_ Ditto,
        collection: char_p::Ref<'_>,
        query: char_p::Ref<'_>,
        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
        order_by: c_slice::Ref<'s, COrderByParam<'l>>,
        limit: c_int,
        offset: c_uint,
    ) -> c_int;

    pub fn ditto_live_query_webhook_generate_new_api_secret(ditto: &'_ Ditto) -> c_int;

    pub fn ditto_live_query_webhook_start_all(ditto: &'_ Ditto) -> c_int;

    pub fn ditto_live_query_webhook_start_by_id(
        ditto: &'_ Ditto,
        id: c_slice::Ref<'_, u8>,
    ) -> c_int;

    pub fn ditto_live_query_webhook_register_str<'s, 'l: 's>(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        query: char_p::Ref<'_>,
        order_by: c_slice::Ref<'s, COrderByParam<'l>>,
        limit: c_int,
        offset: c_uint,
        url: char_p::Ref<'_>,
    ) -> c::Result_BoxedSlice<u8>;

    pub fn ditto_live_query_register_str<'s, 'l: 's>(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        query: char_p::Ref<'_>,
        query_args_cbor: Option<c_slice::Ref<'_, u8>>,
        order_by: c_slice::Ref<'s, COrderByParam<'l>>,
        limit: c_int,
        offset: c_uint,
        lq_availability: LiveQueryAvailability,
        ctx: *mut c_void,
        retain: Option<unsafe extern "C" fn(*mut c_void)>,
        release: Option<unsafe extern "C" fn(*mut c_void)>,
        c_cb: unsafe extern "C" fn(ctx: *mut c_void, params: c_cb_params),
    ) -> c::Result<i64>;

    pub fn ditto_live_query_start(ditto: &'_ Ditto, id: i64) -> c_int;

    pub fn ditto_live_query_stop(ditto: &'_ Ditto, id: i64);

    pub fn ditto_stop_all_live_queries(ditto: &mut Ditto);

    pub fn ditto_live_query_signal_available_next(ditto: &'_ Ditto, id: i64);

    pub fn ditto_documents_hash(documents: c_slice::Ref<'_, c::Box<Document>>) -> c::Result<u64>;

    pub fn ditto_documents_hash_mnemonic(
        documents: c_slice::Ref<'_, c::Box<Document>>,
    ) -> c::Result<Option<char_p::Box>>;

    pub fn ditto_new_attachment_from_file(
        ditto: &'_ Ditto,
        source_path: char_p::Ref<'_>,
        file_operation: AttachmentFileOperation,
        out_attachment: Out<'_, Attachment>,
    ) -> c_uint;

    pub fn ditto_get_complete_attachment_path(
        ditto: &'_ Ditto,
        handle: &'_ AttachmentHandle,
    ) -> char_p::Box;

    pub fn ditto_resolve_attachment(
        ditto: &'_ Ditto,
        id: c_slice::Ref<'_, u8>,
        ctx: *mut c_void,
        retain: Option<unsafe extern "C" fn(*mut c_void)>,
        release: Option<unsafe extern "C" fn(*mut c_void)>,
        on_complete_cb: unsafe extern "C" fn(ctx: *mut c_void, c::Box<AttachmentHandle>),
        on_progress_cb: unsafe extern "C" fn(ctx: *mut c_void, u64, u64),
        on_deleted_cb: unsafe extern "C" fn(ctx: *mut c_void),
    ) -> c::Result<u64>;

    pub fn ditto_cancel_resolve_attachment(
        ditto: &'_ Ditto,
        id: c_slice::Ref<'_, u8>,
        cancel_token: u64,
    ) -> c_uint;

    pub fn ditto_document_update(document: &'_ mut Document, cbor: c_slice::Ref<'_, u8>) -> c_int;

    pub fn ditto_collection_update_multiple(
        ditto: &'_ Ditto,
        coll_name: char_p::Ref<'_>,
        transaction: &'_ mut CWriteTransaction,
        documents: c::Vec<c::Box<Document>>,
    ) -> c_int;

    pub fn ditto_error_message() -> Option<char_p::Box>;

    pub fn ditto_document_cbor(document: &'_ Document) -> c_slice::Box<u8>;

    pub fn ditto_document_get_cbor_with_path_type(
        document: &'_ Document,
        pointer: char_p::Ref<'_>,
        path_type: PathAccessorType,
    ) -> c::Result_BoxedSlice<u8>;

    pub fn ditto_document_get_variant_cbor(
        document: &'_ Document,
        pointer: char_p::Ref<'_>,
        variant: DittoCrdtType,
    ) -> c::Result_BoxedSlice<u8>;

    pub fn ditto_document_set_cbor(
        document: &'_ mut Document,
        pointer: char_p::Ref<'_>,
        cbor: c_slice::Ref<'_, u8>,
    ) -> c_int;

    pub fn ditto_document_set_cbor_with_timestamp(
        document: &'_ mut Document,
        pointer: char_p::Ref<'_>,
        cbor: c_slice::Ref<'_, u8>,
        timestamp: c_uint,
    ) -> c_int;

    pub fn ditto_document_remove(document: &'_ mut Document, pointer: char_p::Ref<'_>) -> c_int;

    pub type Document: Send + Sync;

    #[drop]
    pub fn ditto_document_free(document: c::Box<Document>);

    pub fn ditto_document_increment_counter(
        document: &'_ mut Document,
        pointer: char_p::Ref<'_>,
        amount: c_double,
    ) -> c_int;

    pub type AttachmentHandle: Send + Sync;
    #[drop]
    pub fn ditto_free_attachment_handle(handle: c::Box<AttachmentHandle>);

    pub type StaticTcpClientPlatformHandle: Send + Sync;
    #[drop]
    pub fn static_tcp_client_free_handle(handle: c::Box<StaticTcpClientPlatformHandle>);

    pub type WebsocketClientPlatformHandle: Send + Sync;
    #[drop]
    pub fn websocket_client_free_handle(handle: c::Box<WebsocketClientPlatformHandle>);

    pub type MdnsClientPlatformHandle: Send + Sync;
    #[drop]
    pub fn mdns_client_free_handle(handle: c::Box<MdnsClientPlatformHandle>);

    pub type MdnsServerPlatformHandle: Send + Sync;
    #[drop]
    pub fn mdns_server_free_handle(handle: c::Box<MdnsServerPlatformHandle>);

    pub type BleClientPlatformHandle: Send + Sync;
    #[drop]
    pub fn ble_client_free_handle(handle: c::Box<BleClientPlatformHandle>);

    pub type BleServerPlatformHandle: Send + Sync;
    #[drop]
    pub fn ble_server_free_handle(handle: c::Box<BleServerPlatformHandle>);

    pub fn ditto_free_documents(documents: Option<c::Vec<c::Box<Document>>>);

    pub fn ditto_free_indices(indices: Option<c_slice::Box<usize>>);

    pub fn ditto_c_string_free(s: char_p::Box);

    pub fn ditto_c_bytes_free(bytes: c_slice::Box<u8>);

    pub fn ditto_auth_client_make_with_web(
        working_dir: char_p::Ref<'_>,
        app_id: char_p::Ref<'_>,
        base_url: char_p::Ref<'_>,
        login_provider: Option<BoxedLoginProvider>,
    ) -> c::Result_Box<AuthClient>;

    pub fn ditto_auth_client_make_for_development(
        working_dir: Option<char_p::Ref<'_>>,
        app_id: char_p::Ref<'_>,
        site_id: c_ulonglong,
    ) -> c::Result_Box<AuthClient>;

    pub fn ditto_auth_client_make_anonymous_client(
        working_dir: char_p::Ref<'_>,
        app_id: char_p::Ref<'_>,
        shared_token: char_p::Ref<'_>,
        base_url: char_p::Ref<'_>,
    ) -> c::Result_Box<AuthClient>;

    pub fn ditto_auth_client_make_with_shared_key(
        working_dir: Option<char_p::Ref<'_>>,
        app_id: char_p::Ref<'_>,
        key_der_b64: char_p::Ref<'_>,
        site_id: c_ulonglong,
    ) -> c::Result_Box<AuthClient>;

    pub fn ditto_auth_client_make_with_static_x509(
        config_cbor_b64: char_p::Ref<'_>,
    ) -> c::Result_Box<AuthClient>;

    pub fn ditto_auth_client_make_with_web_with_executor(
        working_dir: char_p::Ref<'_>,
        app_id: char_p::Ref<'_>,
        base_url: char_p::Ref<'_>,
        login_provider: Option<BoxedLoginProvider>,
        executor: c::Box<Executor>,
    ) -> c::Result_Box<AuthClient>;

    pub fn ditto_auth_client_make_for_development_with_executor(
        working_dir: Option<char_p::Ref<'_>>,
        app_id: char_p::Ref<'_>,
        site_id: c_ulonglong,
        executor: c::Box<Executor>,
    ) -> c::Result_Box<AuthClient>;

    pub fn ditto_auth_client_make_anonymous_client_with_executor(
        working_dir: char_p::Ref<'_>,
        app_id: char_p::Ref<'_>,
        shared_token: char_p::Ref<'_>,
        base_url: char_p::Ref<'_>,
        executor: c::Box<Executor>,
    ) -> c::Result_Box<AuthClient>;

    pub fn ditto_auth_client_make_with_shared_key_with_executor(
        working_dir: Option<char_p::Ref<'_>>,
        app_id: char_p::Ref<'_>,
        key_der_b64: char_p::Ref<'_>,
        site_id: c_ulonglong,
        executor: c::Box<Executor>,
    ) -> c::Result_Box<AuthClient>;

    pub fn ditto_auth_client_make_with_static_x509_with_executor(
        config_cbor_b64: char_p::Ref<'_>,
        executor: c::Box<Executor>,
    ) -> c::Result_Box<AuthClient>;

    pub type AuthClient: Send + Sync;

    #[drop]
    pub fn ditto_auth_client_free(auth_client: c::Box<AuthClient>);

    pub fn ditto_auth_client_get_site_id(auth_client: &'_ AuthClient) -> c_ulonglong;

    pub fn ditto_auth_client_get_app_id(auth_client: &'_ AuthClient) -> char_p::Box;

    pub fn ditto_auth_client_user_id(auth_client: &'_ AuthClient) -> Option<char_p::Box>;

    pub fn ditto_auth_client_make_login_provider(
        ctx: *mut c_void,
        retain: Option<unsafe extern "C" fn(*mut c_void)>,
        release: Option<unsafe extern "C" fn(*mut c_void)>,
        expiring_cb: Option<unsafe extern "C" fn(*mut c_void, c_uint)>,
    ) -> BoxedLoginProvider;

    pub fn ditto_auth_client_set_validity_listener(
        auth_client: &'_ AuthClient,
        ctx: *mut c_void,
        retain: Option<unsafe extern "C" fn(*mut c_void)>,
        release: Option<unsafe extern "C" fn(*mut c_void)>,
        validity_update_cb: Option<unsafe extern "C" fn(*mut c_void, c_int, c_int)>,
    );

    pub fn ditto_auth_client_is_web_valid(auth_client: &'_ AuthClient) -> c_int;

    pub fn ditto_auth_client_is_x509_valid(auth_client: &'_ AuthClient) -> c_int;

    pub fn ditto_auth_client_login_with_credentials(
        auth_client: &'_ AuthClient,
        username: char_p::Ref<'_>,
        password: char_p::Ref<'_>,
        provider: char_p::Ref<'_>,
    ) -> c_int;

    pub fn ditto_auth_client_login_with_token_and_feedback(
        auth_client: &'_ AuthClient,
        token: char_p::Ref<'_>,
        provider: char_p::Ref<'_>,
    ) -> AuthenticationResult;

    pub fn ditto_auth_client_login_with_token(
        auth_client: &'_ AuthClient,
        token: char_p::Ref<'_>,
        provider: char_p::Ref<'_>,
    ) -> c_int;

    pub fn ditto_auth_client_logout(auth_client: &'_ AuthClient) -> c_int;

    pub fn ditto_auth_extract_executor(auth_client: &'_ AuthClient) -> c::Box<Executor>;

    pub type LoginProvider: Send + Sync;

    #[drop]
    pub fn ditto_auth_login_provider_free(login_provider: c::Box<LoginProvider>);

    pub fn ditto_insert_timeseries_event(
        ditto: &'_ Ditto,
        timestamp: [u8; 8], // a u64 ... but arm32
        nanos: u32,
        ts_name: char_p::Ref<'_>,
        cbor: c_slice::Ref<'_, u8>,
        txn: Option<&'_ mut CWriteTransaction>,
    ) -> c_int;

    pub fn ditto_set_sync_group(ditto: &'_ Ditto, sync_group: c_uint);

    pub fn ditto_set_device_name(ditto: &'_ Ditto, device_name: char_p::Ref<'_>);

    pub fn ditto_register_presence_v2_callback(
        ditto: &'_ Ditto,
        ctx: *mut c_void,
        retain: Option<unsafe extern "C" fn(*mut c_void)>,
        release: Option<unsafe extern "C" fn(*mut c_void)>,
        c_cb: Option<unsafe extern "C" fn(*mut c_void, json: char_p::Ref<'_>)>,
    );

    pub fn ditto_presence_v2(ditto: &'_ Ditto) -> char_p::Box;

    pub fn ditto_register_presence_callback_v3(
        ditto: &'_ Ditto,
        ctx: *mut c_void,
        retain: Option<unsafe extern "C" fn(*mut c_void)>,
        release: Option<unsafe extern "C" fn(*mut c_void)>,
        c_cb: Option<unsafe extern "C" fn(*mut c_void, json: char_p::Ref<'_>)>,
    );

    pub fn ditto_presence_v3(ditto: &'_ Ditto) -> char_p::Box;

    pub type Executor: Send + Sync;
    pub fn ditto_make_executor_from_handle(handle: Box<Handle>) -> c::Box<Executor>;
    pub fn ditto_make_executor_from_runtime(runtime: Arc<Runtime>) -> c::Box<Executor>;
    pub fn ditto_make_executor_new_runtime() -> c::Box<Executor>;
    #[drop]
    pub fn ditto_executor_free(executor: c::Box<Executor>);

    pub type DiskUsageObserver;

    pub fn ditto_register_disk_usage_callback(
        ditto: &'_ Ditto,
        component: FsComponent,
        ctx: *mut c_void,
        retain: Option<unsafe extern "C" fn(*mut c_void)>,
        release: Option<unsafe extern "C" fn(*mut c_void)>,
        c_cb: Option<unsafe extern "C" fn(*mut c_void, cbor: c_slice::Ref<'_, u8>)>,
    ) -> c::Box<DiskUsageObserver>;
    pub fn ditto_disk_usage(ditto: &'_ Ditto, path: FsComponent) -> c_slice::Box<u8>;
    #[drop]
    pub fn ditto_release_disk_usage_callback(_handle: c::Box<DiskUsageObserver>);
}

#[cfg(test)]
mod test {
    use super::*;

    /// Minimal test to force cargo/rustc to attempt to link to
    /// libdittoffi
    // This should not use ditto_test as it is public
    #[test]
    fn test_linking() {
        unsafe {
            ditto_logger_init();
        }
    }
}