use ::safer_ffi::prelude::*;
use std::os::raw::{c_double, c_int, c_uint, c_ulonglong, c_void};
#[repr(C)]
pub struct Ditto {
_private: [u8; 0],
}
macro_rules! opaque_wrap {(
$pub:vis
type $TypeName:ident ~ repr_c::Box<$Pointee:ty>;
$(
fn drop $($rest:tt)*
)?
) => (
#[repr(transparent)]
$pub
struct $TypeName {
ptr: ::core::ptr::NonNull<$Pointee>,
}
impl ::core::ops::DerefMut for $TypeName {
fn deref_mut (self: &'_ mut Self) -> &'_ mut $Pointee
{
impl ::core::ops::Deref for $TypeName {
type Target = $Pointee;
fn deref (self: &'_ Self) -> &'_ $Pointee
{
unsafe {
self.ptr.as_ref()
}
}
}
unsafe {
self.ptr.as_mut()
}
}
}
unsafe impl ::core::marker::Send for $TypeName {}
unsafe impl ::core::marker::Sync for $TypeName {}
$(
impl Drop for $TypeName {
fn drop $($rest)*
}
)?
)}
opaque_wrap! {
pub type BoxedDitto ~ repr_c::Box<Ditto>;
fn drop(&mut self) {
unsafe {
ditto_drop(self);
}
}
}
#[repr(C)]
pub struct UninitializedDitto {
_private: [u8; 0],
}
opaque_wrap! {
pub type BoxedUninitializedDitto ~ repr_c::Box<UninitializedDitto>;
}
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Platform {
Windows,
Mac,
Ios,
Android,
Linux,
Unknown,
}
#[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 {
Error = 1,
Warning,
Info,
Debug,
Verbose,
}
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WebSocketMode {
Enabled,
Disabled,
}
#[repr(C)]
#[allow(non_camel_case_types)]
pub struct StaticTcpClientPlatformHandle {
_private: [u8; 0],
}
opaque_wrap! {
pub type StaticTcpClient ~ repr_c::Box<StaticTcpClientPlatformHandle>;
fn drop(&mut self) {
unsafe {static_tcp_client_free_handle(&mut **self);}
}
}
#[repr(C)]
#[allow(non_camel_case_types)]
pub struct WebsocketClientPlatformHandle {
_private: [u8; 0],
}
opaque_wrap! {
pub type WebsocketClient ~ repr_c::Box<WebsocketClientPlatformHandle>;
fn drop(&mut self) {
unsafe {websocket_client_free_handle(&mut **self);}
}
}
#[repr(C)]
#[allow(non_camel_case_types)]
pub struct BleClientPlatformHandle {
_private: [u8; 0],
}
opaque_wrap! {
pub type BleClient ~ repr_c::Box<BleClientPlatformHandle>;
fn drop(&mut self) {
unsafe {ble_client_free_handle(&mut **self);}
}
}
#[repr(C)]
#[allow(non_camel_case_types)]
pub struct BleServerPlatformHandle {
_private: [u8; 0],
}
opaque_wrap! {
pub type BleServer ~ repr_c::Box<BleServerPlatformHandle>;
fn drop(&mut self) {
unsafe {ble_server_free_handle(&mut **self);}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(dead_code)]
pub enum LicenseVerificationResult {
LicenseOk = 0,
VerificationFailed = -1,
LicenseExpired = -2,
UnsupportedFutureVersion = -3,
}
#[repr(C)]
pub struct CCompiledQuery {
_private: [u8; 0],
}
opaque_wrap! {
pub type BoxedCCompiledQuery ~ repr_c::Box<CCompiledQuery>;
fn drop(&mut self) {
let ptr: *mut CCompiledQuery = &mut **self;
unsafe {ditto_query_free(ptr);}
}
}
#[repr(C)]
pub struct CWriteTransaction {
_private: [u8; 0],
}
opaque_wrap! {
pub type BoxedWriteTransaction ~ repr_c::Box<CWriteTransaction>;
fn drop(&mut self) {
unsafe {
ditto_write_transaction_free(&mut **self);
}
}
}
#[repr(C)]
pub struct CReadTransaction {
_private: [u8; 0],
}
opaque_wrap! {
pub type BoxedReadTransaction ~ repr_c::Box<CReadTransaction>;
fn drop(&mut self) {
let ptr: *mut CReadTransaction = &mut **self;
unsafe {ditto_read_transaction_free(ptr)}
}
}
#[repr(C)]
pub struct CQueryFilter {
_private: [u8; 0],
}
opaque_wrap! {
pub type BoxedQueryFilter ~ repr_c::Box<CQueryFilter>;
}
#[repr(C)]
pub struct COrderDefinition {
pub projection: BoxedCCompiledQuery,
pub direction: QuerySortDirection,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
#[allow(dead_code)]
pub enum QuerySortDirection {
Ascending = 1,
Descending,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct Document {
_private: [u8; 0],
}
opaque_wrap! {
pub type BoxedDocument ~ repr_c::Box<Document>;
fn drop(&mut self) {
unsafe {
ditto_document_free(self);
}
}
}
use std::fmt;
impl fmt::Debug for BoxedDocument {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let c_str = unsafe { ditto_document_id(self) };
f.debug_struct("Document").field("id", &c_str).finish()
}
}
#[repr(C)]
#[derive(Debug, PartialEq)]
#[allow(dead_code)]
pub enum QueryCompileResult {
Success = 0,
InvalidInput = 1,
CompileFailed = 2,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
#[allow(dead_code)]
pub enum LiveQueryAvailability {
Always,
WhenSignalled,
}
#[repr(C)]
#[allow(nonstandard_style)]
pub struct c_cb_params {
pub documents: repr_c::Vec<BoxedDocument>,
pub is_initial: bool,
pub old_documents: Option<repr_c::Vec<BoxedDocument>>,
pub insertions: Option<c_slice::Box<usize>>,
pub deletions: Option<c_slice::Box<usize>>,
pub updates: Option<c_slice::Box<usize>>,
pub moves: Option<c_slice::Box<usize>>,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
#[allow(dead_code)]
pub enum AttachmentFileOperation {
Copy = 1,
Move,
}
#[repr(C)]
pub struct Attachment {
_private: [u8; 0],
}
#[repr(C)]
pub struct AttachmentHandle {
_private: [u8; 0],
}
opaque_wrap! {
pub type BoxedAttachmentHandle ~ repr_c::Box<AttachmentHandle>;
fn drop(&mut self) {
unsafe {
ditto_free_attachment_handle(self);
}
}
}
#[link(name = "dittoffi")]
extern "C" {
pub fn ditto_init_sdk_version(
platform: Platform,
language: Language,
sdk_semver: char_p::Ref<'_>,
);
pub fn uninitialized_ditto_make(working_dir: char_p::Ref<'_>) -> BoxedUninitializedDitto;
pub fn uninitialized_ditto_get_site_id(uninit_ditto: &'_ UninitializedDitto) -> c_ulonglong;
pub fn ditto_make_development(
uninit_ditto: BoxedUninitializedDitto,
site_id: c_ulonglong,
app_name: char_p::Ref<'_>,
) -> BoxedDitto;
pub fn ditto_make_production(
uninit_ditto: BoxedUninitializedDitto,
certificate_config_str: char_p::Ref<'_>,
) -> BoxedDitto;
pub fn ditto_get_site_id(ditto: &'_ Ditto) -> c_ulonglong;
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);
pub fn ditto_drop(ditto: &'_ mut Ditto);
pub fn ditto_free(ditto: BoxedDitto);
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<'_>) -> StaticTcpClient;
pub fn ditto_add_websocket_client(
ditto: &'_ Ditto,
address: char_p::Ref<'_>,
) -> WebsocketClient;
pub fn ditto_add_internal_ble_client_transport(ditto: &'_ Ditto) -> BleClient;
pub fn ditto_add_internal_ble_server_transport(ditto: &'_ Ditto) -> BleServer;
pub fn ditto_clear_site_id(ditto: &'_ Ditto) -> c_int;
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;
#[allow(improper_ctypes)]
pub fn ditto_get_collection_names(
ditto: &'_ Ditto,
out_names: Out<'_, Option<repr_c::Vec<char_p::Box>>>,
) -> c_int;
pub fn ditto_queries_hash(
ditto: &Ditto,
coll_names: c_slice::Ref<'_, char_p::Ref<'_>>,
queries: c_slice::Ref<'_, &CCompiledQuery>,
c_hash: Out<'_, u64>,
) -> c_int;
pub fn ditto_queries_hash_mnemonic<'_0, '_1: '_0>(
ditto: &'_ Ditto,
coll_names: c_slice::Ref<'_0, char_p::Ref<'_1>>,
queries: c_slice::Ref<'_0, &'_1 CCompiledQuery>,
out_mnemonic_hash: Out<'_, Option<char_p::Box>>,
) -> c_int;
pub fn ditto_collection(ditto: &'_ Ditto, name: char_p::Ref<'_>) -> c_int;
pub fn ditto_collection_insert(
ditto: &'_ Ditto,
coll_name: char_p::Ref<'_>,
transaction: &'_ mut CWriteTransaction,
document: BoxedDocument,
id: Out<'_, Option<char_p::Box>>,
) -> c_int;
pub fn ditto_collection_update(
ditto: &'_ Ditto,
coll_name: char_p::Ref<'_>,
transaction: &'_ mut CWriteTransaction,
document: BoxedDocument,
) -> c_int;
pub fn ditto_collection_evict(
ditto: &'_ Ditto,
coll_name: char_p::Ref<'_>,
transaction: &'_ mut CWriteTransaction,
id: char_p::Ref<'_>,
out_evicted: Option<Out<'_, bool>>,
) -> c_int;
pub fn ditto_collection_remove(
ditto: &'_ Ditto,
coll_name: char_p::Ref<'_>,
transaction: &'_ mut CWriteTransaction,
id: char_p::Ref<'_>,
out_removed: Option<Out<'_, bool>>,
) -> c_int;
pub fn ditto_collection_get(
ditto: &'_ Ditto,
coll_name: char_p::Ref<'_>,
id: char_p::Ref<'_>,
transaction: &'_ mut CReadTransaction,
document: Out<'_, Option<BoxedDocument>>,
) -> c_int;
pub fn ditto_read_transaction<'txn>(
ditto: &'_ Ditto,
txn: Out<'txn, Option<BoxedReadTransaction>>,
) -> c_int;
pub fn ditto_read_transaction_free(transaction: *mut CReadTransaction);
pub fn ditto_write_transaction(
ditto: &'_ Ditto,
txn: Out<'_, Option<BoxedWriteTransaction>>,
) -> c_int;
pub fn ditto_write_transaction_free(txn: *mut CWriteTransaction);
pub fn ditto_write_transaction_commit(
ditto: &Ditto,
transaction: BoxedWriteTransaction,
) -> c_int;
pub fn ditto_document_new_cbor(
cbor: c_slice::Ref<'_, u8>,
id: Option<char_p::Ref<'_>>,
_site_id: c_ulonglong,
document: Out<'_, Option<BoxedDocument>>,
) -> c_int;
pub fn ditto_write_transaction_rollback(transaction: BoxedWriteTransaction);
pub fn ditto_document_new_cbor_with_timestamp(
cbor: c_slice::Ref<'_, u8>,
id: Option<char_p::Ref<'_>>,
_site_id: c_ulonglong,
timestamp: c_uint,
document: Out<'_, Option<BoxedDocument>>,
) -> c_int;
pub fn ditto_document_id(document: &'_ Document) -> char_p::Box;
pub fn ditto_add_subscription(
ditto: &'_ Ditto,
collection: char_p::Ref<'_>,
query: char_p::Ref<'_>,
);
pub fn ditto_remove_subscription(
ditto: &'_ Ditto,
collection: char_p::Ref<'_>,
query: char_p::Ref<'_>,
);
pub fn ditto_query_compile<'__>(
expr: char_p::Ref<'_>,
query: Out<'__, Option<BoxedCCompiledQuery>>,
) -> QueryCompileResult;
pub fn ditto_query_free(query: *mut CCompiledQuery);
#[allow(improper_ctypes)]
pub fn ditto_live_query_register(
ditto: &'_ Ditto,
coll_name: char_p::Ref<'_>,
query: &'_ CCompiledQuery,
order_by: c_slice::Ref<'_, COrderDefinition>,
limit: c_int,
offset: c_uint,
lq_availability: LiveQueryAvailability,
id: Out<'_, i64>,
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_int;
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_new_attachment_from_file(
ditto: &'_ Ditto,
source_path: char_p::Ref<'_>,
file_operation: AttachmentFileOperation,
out_attachment: Out<'_, Attachment>,
) -> c_uint;
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)>,
out_cancel_token: Out<'_, u64>,
on_complete_cb: unsafe extern "C" fn(ctx: *mut c_void, BoxedAttachmentHandle),
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_uint;
pub fn ditto_document_update(
document: &'_ mut Document,
cbor: c_slice::Ref<'_, u8>,
create_path: bool,
) -> c_int;
pub fn ditto_query_filter_next<'__, 'iter: '__>(
ditto: &Ditto,
query_filter: &'__ mut CQueryFilter,
document: Out<'_, Option<BoxedDocument>>,
) -> c_int;
pub fn ditto_read_transaction_query<'query_ref, 'query: 'query_ref, 'txn: 'query>(
ditto: &'_ Ditto,
coll_name: char_p::Ref<'_>,
transaction: &'txn mut CReadTransaction,
query: &'_ CCompiledQuery,
order_by: c_slice::Ref<'_, COrderDefinition>,
limit: c_int,
offset: c_uint,
query_filter: Out<'query_ref, Option<BoxedQueryFilter>>,
) -> c_int;
pub fn ditto_collection_update_multiple(
ditto: &'_ Ditto,
coll_name: char_p::Ref<'_>,
transaction: &'_ mut CWriteTransaction,
documents: repr_c::Vec<BoxedDocument>,
) -> 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_json(document: &'_ Document) -> char_p::Box;
#[allow(improper_ctypes)]
pub fn ditto_document_get_cbor(
document: &'_ Document,
pointer: char_p::Ref<'_>,
) -> Option<c_slice::Box<u8>>;
pub fn ditto_document_set_cbor(
document: &'_ mut Document,
pointer: char_p::Ref<'_>,
cbor: c_slice::Ref<'_, u8>,
create_path: bool,
) -> c_int;
pub fn ditto_document_set_cbor_with_timestamp(
document: &'_ mut Document,
pointer: char_p::Ref<'_>,
cbor: c_slice::Ref<'_, u8>,
create_path: bool,
timestamp: c_uint,
) -> c_int;
pub fn ditto_document_remove(document: &'_ mut Document, pointer: char_p::Ref<'_>) -> c_int;
pub fn ditto_document_insert_cbor(
document: &'_ mut Document,
pointer: char_p::Ref<'_>,
cbor: c_slice::Ref<'_, u8>,
) -> c_int;
pub fn ditto_document_push_cbor(
document: &'_ mut Document,
pointer: char_p::Ref<'_>,
cbor: c_slice::Ref<'_, u8>,
) -> c_int;
pub fn ditto_document_pop_cbor(
document: &'_ mut Document,
pointer: char_p::Ref<'_>,
out_cbor: Out<'_, c_slice::Box<u8>>,
) -> c_int;
pub fn ditto_document_free(document: &mut Document);
pub fn ditto_document_replace_with_counter(
document: &'_ mut Document,
pointer: char_p::Ref<'_>,
) -> c_int;
pub fn ditto_document_replace_with_counter_with_timestamp(
document: &'_ mut Document,
pointer: char_p::Ref<'_>,
timestamp: c_uint,
) -> c_int;
pub fn ditto_document_increment_counter(
document: &'_ mut Document,
pointer: char_p::Ref<'_>,
amount: c_double,
) -> c_int;
pub fn ditto_free_attachment_handle(handle: &mut AttachmentHandle);
pub fn static_tcp_client_free_handle(handle: *mut StaticTcpClientPlatformHandle);
pub fn websocket_client_free_handle(handle: *mut WebsocketClientPlatformHandle);
pub fn ble_client_free_handle(handle: *mut BleClientPlatformHandle);
pub fn ble_server_free_handle(handle: *mut BleServerPlatformHandle);
#[allow(improper_ctypes)]
pub fn ditto_free_documents(documents: Option<repr_c::Vec<BoxedDocument>>);
#[allow(improper_ctypes)]
pub fn ditto_free_indices(indices: Option<c_slice::Box<usize>>);
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_linking() {
unsafe {
ditto_logger_init();
}
}
}