dittolive_ditto/presence/
observer.rs

1use_prelude!();
2
3use std::hash::Hash;
4
5use ffi_sdk::{DynFfiPresenceCallback, FfiPresenceObserver};
6use uuid::Uuid;
7
8use crate::error::Result;
9
10trait_alias! {
11    pub trait PresenceCallback = FnMut(&PresenceGraph) + Send + Sync + 'static
12}
13
14/// Use [`ditto.presence().register_observer(...)`] to create a new `PresenceObserver`.
15///
16/// # Example
17///
18/// ```
19/// use dittolive_ditto::Ditto;
20/// # fn example(ditto: &Ditto) -> anyhow::Result<()> {
21///
22/// // To register a new presence observer
23/// let observer = ditto.presence().register_observer(|graph| {
24///     println!("Graph updated: {:?}", graph);
25/// })?;
26///
27/// // Later, to cancel the observer
28/// observer.cancel();
29/// # Ok(())
30/// # }
31/// ```
32///
33/// [`ditto.presence().register_observer(...)`]: crate::presence::Presence::register_observer
34pub struct PresenceObserver {
35    pub(crate) handle: repr_c::Box<FfiPresenceObserver>,
36}
37
38impl PresenceObserver {
39    /// Create a new `PresenceObserver` with the given callback to receive presence updates.
40    pub(crate) fn new<F>(ditto: &ffi_sdk::BoxedDitto, mut observer: F) -> Result<PresenceObserver>
41    where
42        F: PresenceCallback,
43    {
44        let ffi_callback: repr_c::Box<DynFfiPresenceCallback> =
45            Box::new(move |graph: c_slice::Box<u8>, _: Blocking| {
46                let graph =
47                    serde_json::from_slice(&graph).expect("should deserialize presence graph");
48                observer(&graph);
49            })
50            .into();
51
52        let handle = ffi_sdk::dittoffi_presence_register_observer_throws(ditto, ffi_callback)
53            .into_rust_result()?;
54        Ok(Self { handle })
55    }
56
57    /// Cancels this [`PresenceObserver`]. The registered callback will no longer be called.
58    pub fn cancel(&self) {
59        ffi_sdk::dittoffi_presence_observer_cancel(&self.handle);
60    }
61
62    /// Returns whether this [`PresenceObserver`] has been cancelled.
63    pub fn is_cancelled(&self) -> bool {
64        ffi_sdk::dittoffi_presence_observer_is_cancelled(&self.handle)
65    }
66
67    /// Returns the unique identifier for this [`PresenceObserver`].
68    fn id(&self) -> Uuid {
69        let buffer = ffi_sdk::dittoffi_presence_observer_id(&self.handle);
70        Uuid::from_slice(buffer.as_slice()).expect("bug: expected valid UUID")
71    }
72}
73
74impl Eq for PresenceObserver {}
75impl PartialEq for PresenceObserver {
76    fn eq(&self, other: &Self) -> bool {
77        self.id() == other.id()
78    }
79}
80
81impl Hash for PresenceObserver {
82    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
83        self.id().hash(state);
84    }
85}