use std::{
cmp::Ordering,
hash::{self, Hash},
};
use ffi_sdk::{
ffi_utils::{c_slice, char_p, repr_c},
FfiSyncSubscription,
};
use crate::{
ditto::Ditto,
error::DittoError,
utils::{extension_traits::FfiResultIntoRustResult, zstr::zstr},
};
pub struct SyncSubscription {
pub(crate) handle: repr_c::Box<FfiSyncSubscription>,
}
impl SyncSubscription {
pub(crate) fn new(
ditto: &Ditto,
query: &zstr,
query_args: Option<&[u8]>,
) -> Result<Self, DittoError> {
let handle = ffi_sdk::dittoffi_sync_register_subscription_throws(
&ditto.ditto,
query.into(),
query_args.map(|a| a.into()),
)
.into_rust_result()?;
Ok(Self { handle })
}
pub fn query_string(&self) -> String {
let cbox: char_p::Box = ffi_sdk::dittoffi_sync_subscription_query_string(&self.handle);
cbox.into_string()
}
pub fn query_arguments(&self) -> Option<serde_cbor::Value> {
let buffer: c_slice::Box<u8> =
ffi_sdk::dittoffi_sync_subscription_query_arguments_cbor(&self.handle)?;
let cbor = serde_cbor::from_slice(buffer.as_slice())
.unwrap_or_else(|error| panic!("bug: failed to deserialize CBOR from FFI: {error}"));
Some(cbor)
}
pub fn query_arguments_cbor_data(&self) -> Option<Vec<u8>> {
let buffer: c_slice::Box<u8> =
ffi_sdk::dittoffi_sync_subscription_query_arguments_cbor(&self.handle)?;
Some(buffer.as_slice().to_vec())
}
pub fn query_arguments_json_str(&self) -> Option<String> {
let buffer: c_slice::Box<u8> =
ffi_sdk::dittoffi_sync_subscription_query_arguments_json(&self.handle)?;
let json = String::from_utf8(buffer.as_slice().to_vec())
.unwrap_or_else(|error| panic!("bug: failed to deserialize JSON from FFI: {error}"));
Some(json)
}
pub fn cancel(&self) {
ffi_sdk::dittoffi_sync_subscription_cancel(&self.handle);
}
pub fn is_cancelled(&self) -> bool {
ffi_sdk::dittoffi_sync_subscription_is_cancelled(&self.handle)
}
fn id(&self) -> impl '_ + Ord + Hash + core::fmt::Debug {
ffi_sdk::dittoffi_sync_subscription_id(&self.handle)
}
}
impl std::fmt::Debug for SyncSubscription {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SyncSubscription")
.field("id", &self.id())
.finish_non_exhaustive()
}
}
impl std::fmt::Display for SyncSubscription {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}
impl Ord for SyncSubscription {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&self.id(), &other.id())
}
}
impl PartialOrd for SyncSubscription {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(Ord::cmp(self, other))
}
}
impl Eq for SyncSubscription {}
impl PartialEq for SyncSubscription {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl Hash for SyncSubscription {
fn hash<H: hash::Hasher>(&self, h: &mut H) {
self.id().hash(h)
}
}