zbus/
object_server.rs

1use event_listener::{Event, EventListener};
2use serde::Serialize;
3use std::{
4    collections::{hash_map::Entry, HashMap},
5    convert::TryInto,
6    fmt::Write,
7    marker::PhantomData,
8    ops::{Deref, DerefMut},
9    sync::Arc,
10};
11use tracing::{debug, instrument, trace};
12
13use static_assertions::assert_impl_all;
14use zbus_names::InterfaceName;
15use zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Signature, Type, Value};
16
17use crate::{
18    async_lock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
19    fdo,
20    fdo::{Introspectable, ManagedObjects, ObjectManager, Peer, Properties},
21    Connection, DispatchResult, Error, Interface, Message, Result, SignalContext, WeakConnection,
22};
23
24/// Opaque structure that derefs to an `Interface` type.
25pub struct InterfaceDeref<'d, I> {
26    iface: RwLockReadGuard<'d, dyn Interface>,
27    phantom: PhantomData<I>,
28}
29
30impl<I> Deref for InterfaceDeref<'_, I>
31where
32    I: Interface,
33{
34    type Target = I;
35
36    fn deref(&self) -> &I {
37        self.iface.downcast_ref::<I>().unwrap()
38    }
39}
40
41/// Opaque structure that mutably derefs to an `Interface` type.
42pub struct InterfaceDerefMut<'d, I> {
43    iface: RwLockWriteGuard<'d, dyn Interface>,
44    phantom: PhantomData<I>,
45}
46
47impl<I> Deref for InterfaceDerefMut<'_, I>
48where
49    I: Interface,
50{
51    type Target = I;
52
53    fn deref(&self) -> &I {
54        self.iface.downcast_ref::<I>().unwrap()
55    }
56}
57
58impl<I> DerefMut for InterfaceDerefMut<'_, I>
59where
60    I: Interface,
61{
62    fn deref_mut(&mut self) -> &mut Self::Target {
63        self.iface.downcast_mut::<I>().unwrap()
64    }
65}
66
67/// Wrapper over an interface, along with its corresponding `SignalContext`
68/// instance. A reference to the underlying interface may be obtained via
69/// [`InterfaceRef::get`] and [`InterfaceRef::get_mut`].
70pub struct InterfaceRef<I> {
71    ctxt: SignalContext<'static>,
72    lock: Arc<RwLock<dyn Interface>>,
73    phantom: PhantomData<I>,
74}
75
76impl<I> InterfaceRef<I>
77where
78    I: 'static,
79{
80    /// Get a reference to the underlying interface.
81    ///
82    /// **WARNING:** If methods (e.g property setters) in `ObjectServer` require `&mut self`
83    /// `ObjectServer` will not be able to access the interface in question until all references
84    /// of this method are dropped, it is highly recommended that the scope of the interface
85    /// returned is restricted.
86    pub async fn get(&self) -> InterfaceDeref<'_, I> {
87        let iface = self.lock.read().await;
88
89        iface
90            .downcast_ref::<I>()
91            .expect("Unexpected interface type");
92
93        InterfaceDeref {
94            iface,
95            phantom: PhantomData,
96        }
97    }
98
99    /// Get a reference to the underlying interface.
100    ///
101    /// **WARNINGS:** Since the `ObjectServer` will not be able to access the interface in question
102    /// until the return value of this method is dropped, it is highly recommended that the scope
103    /// of the interface returned is restricted.
104    ///
105    /// # Errors
106    ///
107    /// If the interface at this instance's path is not valid, `Error::InterfaceNotFound` error is
108    /// returned.
109    ///
110    /// # Examples
111    ///
112    /// ```no_run
113    /// # use std::error::Error;
114    /// # use async_io::block_on;
115    /// # use zbus::{Connection, dbus_interface};
116    ///
117    /// struct MyIface(u32);
118    ///
119    /// #[dbus_interface(name = "org.myiface.MyIface")]
120    /// impl MyIface {
121    ///    #[dbus_interface(property)]
122    ///    async fn count(&self) -> u32 {
123    ///        self.0
124    ///    }
125    /// }
126    ///
127    /// # block_on(async {
128    /// // Setup connection and object_server etc here and then in another part of the code:
129    /// # let connection = Connection::session().await?;
130    /// #
131    /// # let path = "/org/zbus/path";
132    /// # connection.object_server().at(path, MyIface(22)).await?;
133    /// let object_server = connection.object_server();
134    /// let iface_ref = object_server.interface::<_, MyIface>(path).await?;
135    /// let mut iface = iface_ref.get_mut().await;
136    /// iface.0 = 42;
137    /// iface.count_changed(iface_ref.signal_context()).await?;
138    /// # Ok::<_, Box<dyn Error + Send + Sync>>(())
139    /// # })?;
140    /// #
141    /// # Ok::<_, Box<dyn Error + Send + Sync>>(())
142    /// ```
143    pub async fn get_mut(&self) -> InterfaceDerefMut<'_, I> {
144        let mut iface = self.lock.write().await;
145
146        iface
147            .downcast_ref::<I>()
148            .expect("Unexpected interface type");
149        iface
150            .downcast_mut::<I>()
151            .expect("Unexpected interface type");
152
153        InterfaceDerefMut {
154            iface,
155            phantom: PhantomData,
156        }
157    }
158
159    pub fn signal_context(&self) -> &SignalContext<'static> {
160        &self.ctxt
161    }
162}
163
164impl<I> Clone for InterfaceRef<I> {
165    fn clone(&self) -> Self {
166        Self {
167            ctxt: self.ctxt.clone(),
168            lock: self.lock.clone(),
169            phantom: PhantomData,
170        }
171    }
172}
173
174#[derive(Default, derivative::Derivative)]
175#[derivative(Debug)]
176pub(crate) struct Node {
177    path: OwnedObjectPath,
178    children: HashMap<String, Node>,
179    #[derivative(Debug = "ignore")]
180    interfaces: HashMap<InterfaceName<'static>, Arc<RwLock<dyn Interface>>>,
181}
182
183impl Node {
184    pub(crate) fn new(path: OwnedObjectPath) -> Self {
185        let mut node = Self {
186            path,
187            ..Default::default()
188        };
189        node.at(Peer::name(), || Arc::new(RwLock::new(Peer)));
190        node.at(Introspectable::name(), || {
191            Arc::new(RwLock::new(Introspectable))
192        });
193        node.at(Properties::name(), || Arc::new(RwLock::new(Properties)));
194
195        node
196    }
197
198    // Get the child Node at path.
199    pub(crate) fn get_child(&self, path: &ObjectPath<'_>) -> Option<&Node> {
200        let mut node = self;
201
202        for i in path.split('/').skip(1) {
203            if i.is_empty() {
204                continue;
205            }
206            match node.children.get(i) {
207                Some(n) => node = n,
208                None => return None,
209            }
210        }
211
212        Some(node)
213    }
214
215    // Get the child Node at path. Optionally create one if it doesn't exist.
216    // It also returns the path of parent node that implements ObjectManager (if any). If multiple
217    // parents implement it (they shouldn't), then the closest one is returned.
218    fn get_child_mut(
219        &mut self,
220        path: &ObjectPath<'_>,
221        create: bool,
222    ) -> (Option<&mut Node>, Option<ObjectPath<'_>>) {
223        let mut node = self;
224        let mut node_path = String::new();
225        let mut obj_manager_path = None;
226
227        for i in path.split('/').skip(1) {
228            if i.is_empty() {
229                continue;
230            }
231
232            if node.interfaces.contains_key(&ObjectManager::name()) {
233                obj_manager_path = Some((*node.path).clone());
234            }
235
236            write!(&mut node_path, "/{i}").unwrap();
237            match node.children.entry(i.into()) {
238                Entry::Vacant(e) => {
239                    if create {
240                        let path = node_path.as_str().try_into().expect("Invalid Object Path");
241                        node = e.insert(Node::new(path));
242                    } else {
243                        return (None, obj_manager_path);
244                    }
245                }
246                Entry::Occupied(e) => node = e.into_mut(),
247            }
248        }
249
250        (Some(node), obj_manager_path)
251    }
252
253    pub(crate) fn interface_lock(
254        &self,
255        interface_name: InterfaceName<'_>,
256    ) -> Option<Arc<RwLock<dyn Interface>>> {
257        self.interfaces.get(&interface_name).cloned()
258    }
259
260    fn remove_interface(&mut self, interface_name: InterfaceName<'static>) -> bool {
261        self.interfaces.remove(&interface_name).is_some()
262    }
263
264    fn is_empty(&self) -> bool {
265        !self.interfaces.keys().any(|k| {
266            *k != Peer::name()
267                && *k != Introspectable::name()
268                && *k != Properties::name()
269                && *k != ObjectManager::name()
270        })
271    }
272
273    fn remove_node(&mut self, node: &str) -> bool {
274        self.children.remove(node).is_some()
275    }
276
277    // Takes a closure so caller can avoid having to create an Arc & RwLock in case interface was
278    // already added.
279    fn at<F>(&mut self, name: InterfaceName<'static>, iface_creator: F) -> bool
280    where
281        F: FnOnce() -> Arc<RwLock<dyn Interface>>,
282    {
283        match self.interfaces.entry(name) {
284            Entry::Vacant(e) => e.insert(iface_creator()),
285            Entry::Occupied(_) => return false,
286        };
287
288        true
289    }
290
291    #[async_recursion::async_recursion]
292    async fn introspect_to_writer<W: Write + Send>(&self, writer: &mut W, level: usize) {
293        if level == 0 {
294            writeln!(
295                writer,
296                r#"
297<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
298 "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
299<node>"#
300            )
301            .unwrap();
302        }
303
304        for iface in self.interfaces.values() {
305            iface.read().await.introspect_to_writer(writer, level + 2);
306        }
307
308        for (path, node) in &self.children {
309            let level = level + 2;
310            writeln!(
311                writer,
312                "{:indent$}<node name=\"{}\">",
313                "",
314                path,
315                indent = level
316            )
317            .unwrap();
318            node.introspect_to_writer(writer, level).await;
319            writeln!(writer, "{:indent$}</node>", "", indent = level).unwrap();
320        }
321
322        if level == 0 {
323            writeln!(writer, "</node>").unwrap();
324        }
325    }
326
327    pub(crate) async fn introspect(&self) -> String {
328        let mut xml = String::with_capacity(1024);
329
330        self.introspect_to_writer(&mut xml, 0).await;
331
332        xml
333    }
334
335    #[async_recursion::async_recursion]
336    pub(crate) async fn get_managed_objects(&self) -> ManagedObjects {
337        // Recursively get all properties of all interfaces of descendants.
338        let mut managed_objects = ManagedObjects::new();
339        for node in self.children.values() {
340            let mut interfaces = HashMap::new();
341            for iface_name in node.interfaces.keys().filter(|n| {
342                // Filter standard interfaces.
343                *n != &Peer::name()
344                    && *n != &Introspectable::name()
345                    && *n != &Properties::name()
346                    && *n != &ObjectManager::name()
347            }) {
348                let props = node.get_properties(iface_name.clone()).await;
349                interfaces.insert(iface_name.clone().into(), props);
350            }
351            managed_objects.insert(node.path.clone(), interfaces);
352            managed_objects.extend(node.get_managed_objects().await);
353        }
354
355        managed_objects
356    }
357
358    async fn get_properties(
359        &self,
360        interface_name: InterfaceName<'_>,
361    ) -> HashMap<String, OwnedValue> {
362        self.interface_lock(interface_name)
363            .expect("Interface was added but not found")
364            .read()
365            .await
366            .get_all()
367            .await
368    }
369}
370
371/// An object server, holding server-side D-Bus objects & interfaces.
372///
373/// Object servers hold interfaces on various object paths, and expose them over D-Bus.
374///
375/// All object paths will have the standard interfaces implemented on your behalf, such as
376/// `org.freedesktop.DBus.Introspectable` or `org.freedesktop.DBus.Properties`.
377///
378/// # Example
379///
380/// This example exposes the `org.myiface.Example.Quit` method on the `/org/zbus/path`
381/// path.
382///
383/// ```no_run
384/// # use std::error::Error;
385/// use zbus::{Connection, dbus_interface};
386/// use event_listener::Event;
387/// # use async_io::block_on;
388///
389/// struct Example {
390///     // Interfaces are owned by the ObjectServer. They can have
391///     // `&mut self` methods.
392///     quit_event: Event,
393/// }
394///
395/// impl Example {
396///     fn new(quit_event: Event) -> Self {
397///         Self { quit_event }
398///     }
399/// }
400///
401/// #[dbus_interface(name = "org.myiface.Example")]
402/// impl Example {
403///     // This will be the "Quit" D-Bus method.
404///     async fn quit(&mut self) {
405///         self.quit_event.notify(1);
406///     }
407///
408///     // See `dbus_interface` documentation to learn
409///     // how to expose properties & signals as well.
410/// }
411///
412/// # block_on(async {
413/// let connection = Connection::session().await?;
414///
415/// let quit_event = Event::new();
416/// let quit_listener = quit_event.listen();
417/// let interface = Example::new(quit_event);
418/// connection
419///     .object_server()
420///     .at("/org/zbus/path", interface)
421///     .await?;
422///
423/// quit_listener.await;
424/// # Ok::<_, Box<dyn Error + Send + Sync>>(())
425/// # })?;
426/// # Ok::<_, Box<dyn Error + Send + Sync>>(())
427/// ```
428#[derive(Debug)]
429pub struct ObjectServer {
430    conn: WeakConnection,
431    root: RwLock<Node>,
432}
433
434assert_impl_all!(ObjectServer: Send, Sync, Unpin);
435
436impl ObjectServer {
437    /// Creates a new D-Bus `ObjectServer`.
438    pub(crate) fn new(conn: &Connection) -> Self {
439        Self {
440            conn: conn.into(),
441            root: RwLock::new(Node::new("/".try_into().expect("zvariant bug"))),
442        }
443    }
444
445    pub(crate) fn root(&self) -> &RwLock<Node> {
446        &self.root
447    }
448
449    /// Register a D-Bus [`Interface`] at a given path. (see the example above)
450    ///
451    /// Typically you'd want your interfaces to be registered immediately after the associated
452    /// connection is established and therefore use [`zbus::ConnectionBuilder::serve_at`] instead.
453    /// However, there are situations where you'd need to register interfaces dynamically and that's
454    /// where this method becomes useful.
455    ///
456    /// If the interface already exists at this path, returns false.
457    pub async fn at<'p, P, I>(&self, path: P, iface: I) -> Result<bool>
458    where
459        I: Interface,
460        P: TryInto<ObjectPath<'p>>,
461        P::Error: Into<Error>,
462    {
463        self.at_ready(path, I::name(), move || Arc::new(RwLock::new(iface)))
464            .await
465    }
466
467    /// Same as `at` but expects an interface already in `Arc<RwLock<dyn Interface>>` form.
468    // FIXME: Better name?
469    pub(crate) async fn at_ready<'node, 'p, P, F>(
470        &'node self,
471        path: P,
472        name: InterfaceName<'static>,
473        iface_creator: F,
474    ) -> Result<bool>
475    where
476        // Needs to be hardcoded as 'static instead of 'p like most other
477        // functions, due to https://github.com/rust-lang/rust/issues/63033
478        // (It doesn't matter a whole lot since this is an internal-only API
479        // anyway.)
480        P: TryInto<ObjectPath<'p>>,
481        P::Error: Into<Error>,
482        F: FnOnce() -> Arc<RwLock<dyn Interface + 'static>>,
483    {
484        let path = path.try_into().map_err(Into::into)?;
485        let mut root = self.root().write().await;
486        let (node, manager_path) = root.get_child_mut(&path, true);
487        let node = node.unwrap();
488        let added = node.at(name.clone(), iface_creator);
489        if added {
490            if name == ObjectManager::name() {
491                // Just added an object manager. Need to signal all managed objects under it.
492                let ctxt = SignalContext::new(&self.connection(), path)?;
493                let objects = node.get_managed_objects().await;
494                for (path, owned_interfaces) in objects {
495                    let interfaces = owned_interfaces
496                        .iter()
497                        .map(|(i, props)| {
498                            let props = props
499                                .iter()
500                                .map(|(k, v)| (k.as_str(), Value::from(v)))
501                                .collect();
502                            (i.into(), props)
503                        })
504                        .collect();
505                    ObjectManager::interfaces_added(&ctxt, &path, &interfaces).await?;
506                }
507            } else if let Some(manager_path) = manager_path {
508                let ctxt = SignalContext::new(&self.connection(), manager_path.clone())?;
509                let mut interfaces = HashMap::new();
510                let owned_props = node.get_properties(name.clone()).await;
511                let props = owned_props
512                    .iter()
513                    .map(|(k, v)| (k.as_str(), Value::from(v)))
514                    .collect();
515                interfaces.insert(name, props);
516
517                ObjectManager::interfaces_added(&ctxt, &path, &interfaces).await?;
518            }
519        }
520
521        Ok(added)
522    }
523
524    /// Unregister a D-Bus [`Interface`] at a given path.
525    ///
526    /// If there are no more interfaces left at that path, destroys the object as well.
527    /// Returns whether the object was destroyed.
528    pub async fn remove<'p, I, P>(&self, path: P) -> Result<bool>
529    where
530        I: Interface,
531        P: TryInto<ObjectPath<'p>>,
532        P::Error: Into<Error>,
533    {
534        let path = path.try_into().map_err(Into::into)?;
535        let mut root = self.root.write().await;
536        let (node, manager_path) = root.get_child_mut(&path, false);
537        let node = node.ok_or(Error::InterfaceNotFound)?;
538        if !node.remove_interface(I::name()) {
539            return Err(Error::InterfaceNotFound);
540        }
541        if let Some(manager_path) = manager_path {
542            let ctxt = SignalContext::new(&self.connection(), manager_path.clone())?;
543            ObjectManager::interfaces_removed(&ctxt, &path, &[I::name()]).await?;
544        }
545        if node.is_empty() {
546            let mut path_parts = path.rsplit('/').filter(|i| !i.is_empty());
547            let last_part = path_parts.next().unwrap();
548            let ppath = ObjectPath::from_string_unchecked(
549                path_parts.fold(String::new(), |a, p| format!("/{p}{a}")),
550            );
551            root.get_child_mut(&ppath, false)
552                .0
553                .unwrap()
554                .remove_node(last_part);
555            return Ok(true);
556        }
557        Ok(false)
558    }
559
560    /// Get the interface at the given path.
561    ///
562    /// # Errors
563    ///
564    /// If the interface is not registered at the given path, `Error::InterfaceNotFound` error is
565    /// returned.
566    ///
567    /// # Examples
568    ///
569    /// The typical use of this is property changes outside of a dispatched handler:
570    ///
571    /// ```no_run
572    /// # use std::error::Error;
573    /// # use zbus::{Connection, dbus_interface};
574    /// # use async_io::block_on;
575    /// #
576    /// struct MyIface(u32);
577    ///
578    /// #[dbus_interface(name = "org.myiface.MyIface")]
579    /// impl MyIface {
580    ///      #[dbus_interface(property)]
581    ///      async fn count(&self) -> u32 {
582    ///          self.0
583    ///      }
584    /// }
585    ///
586    /// # block_on(async {
587    /// # let connection = Connection::session().await?;
588    /// #
589    /// # let path = "/org/zbus/path";
590    /// # connection.object_server().at(path, MyIface(0)).await?;
591    /// let iface_ref = connection
592    ///     .object_server()
593    ///     .interface::<_, MyIface>(path).await?;
594    /// let mut iface = iface_ref.get_mut().await;
595    /// iface.0 = 42;
596    /// iface.count_changed(iface_ref.signal_context()).await?;
597    /// # Ok::<_, Box<dyn Error + Send + Sync>>(())
598    /// # })?;
599    /// #
600    /// # Ok::<_, Box<dyn Error + Send + Sync>>(())
601    /// ```
602    pub async fn interface<'p, P, I>(&self, path: P) -> Result<InterfaceRef<I>>
603    where
604        I: Interface,
605        P: TryInto<ObjectPath<'p>>,
606        P::Error: Into<Error>,
607    {
608        let path = path.try_into().map_err(Into::into)?;
609        let root = self.root().read().await;
610        let node = root.get_child(&path).ok_or(Error::InterfaceNotFound)?;
611
612        let lock = node
613            .interface_lock(I::name())
614            .ok_or(Error::InterfaceNotFound)?
615            .clone();
616
617        // Ensure what we return can later be dowcasted safely.
618        lock.read()
619            .await
620            .downcast_ref::<I>()
621            .ok_or(Error::InterfaceNotFound)?;
622
623        let conn = self.connection();
624        // SAFETY: We know that there is a valid path on the node as we already converted w/o error.
625        let ctxt = SignalContext::new(&conn, path).unwrap().into_owned();
626
627        Ok(InterfaceRef {
628            ctxt,
629            lock,
630            phantom: PhantomData,
631        })
632    }
633
634    #[instrument(skip(self, connection))]
635    async fn dispatch_method_call_try(
636        &self,
637        connection: &Connection,
638        msg: &Message,
639    ) -> fdo::Result<Result<()>> {
640        let path = msg
641            .path()
642            .ok_or_else(|| fdo::Error::Failed("Missing object path".into()))?;
643        let iface_name = msg
644            .interface()
645            // TODO: In the absence of an INTERFACE field, if two or more interfaces on the same
646            // object have a method with the same name, it is undefined which of those
647            // methods will be invoked. Implementations may choose to either return an
648            // error, or deliver the message as though it had an arbitrary one of those
649            // interfaces.
650            .ok_or_else(|| fdo::Error::Failed("Missing interface".into()))?;
651        let member = msg
652            .member()
653            .ok_or_else(|| fdo::Error::Failed("Missing member".into()))?;
654
655        // Ensure the root lock isn't held while dispatching the message. That
656        // way, the object server can be mutated during that time.
657        let iface = {
658            let root = self.root.read().await;
659            let node = root
660                .get_child(&path)
661                .ok_or_else(|| fdo::Error::UnknownObject(format!("Unknown object '{path}'")))?;
662
663            node.interface_lock(iface_name.as_ref()).ok_or_else(|| {
664                fdo::Error::UnknownInterface(format!("Unknown interface '{iface_name}'"))
665            })?
666        };
667
668        trace!("acquiring read lock on interface `{}`", iface_name);
669        let read_lock = iface.read().await;
670        trace!("acquired read lock on interface `{}`", iface_name);
671        match read_lock.call(self, connection, msg, member.as_ref()) {
672            DispatchResult::NotFound => {
673                return Err(fdo::Error::UnknownMethod(format!(
674                    "Unknown method '{member}'"
675                )));
676            }
677            DispatchResult::Async(f) => {
678                return Ok(f.await);
679            }
680            DispatchResult::RequiresMut => {}
681        }
682        drop(read_lock);
683        trace!("acquiring write lock on interface `{}`", iface_name);
684        let mut write_lock = iface.write().await;
685        trace!("acquired write lock on interface `{}`", iface_name);
686        match write_lock.call_mut(self, connection, msg, member.as_ref()) {
687            DispatchResult::NotFound => {}
688            DispatchResult::RequiresMut => {}
689            DispatchResult::Async(f) => {
690                return Ok(f.await);
691            }
692        }
693        drop(write_lock);
694        Err(fdo::Error::UnknownMethod(format!(
695            "Unknown method '{member}'"
696        )))
697    }
698
699    #[instrument(skip(self, connection))]
700    async fn dispatch_method_call(&self, connection: &Connection, msg: &Message) -> Result<()> {
701        match self.dispatch_method_call_try(connection, msg).await {
702            Err(e) => {
703                let hdr = msg.header()?;
704                debug!("Returning error: {}", e);
705                connection.reply_dbus_error(&hdr, e).await?;
706                Ok(())
707            }
708            Ok(r) => r,
709        }
710    }
711
712    /// Dispatch an incoming message to a registered interface.
713    ///
714    /// The object server will handle the message by:
715    ///
716    /// - looking up the called object path & interface,
717    ///
718    /// - calling the associated method if one exists,
719    ///
720    /// - returning a message (responding to the caller with either a return or error message) to
721    ///   the caller through the associated server connection.
722    ///
723    /// Returns an error if the message is malformed, true if it's handled, false otherwise.
724    #[instrument(skip(self))]
725    pub(crate) async fn dispatch_message(&self, msg: &Message) -> Result<bool> {
726        let conn = self.connection();
727        self.dispatch_method_call(&conn, msg).await?;
728        trace!("Handled: {}", msg);
729
730        Ok(true)
731    }
732
733    pub(crate) fn connection(&self) -> Connection {
734        self.conn
735            .upgrade()
736            .expect("ObjectServer can't exist w/o an associated Connection")
737    }
738}
739
740impl From<crate::blocking::ObjectServer> for ObjectServer {
741    fn from(server: crate::blocking::ObjectServer) -> Self {
742        server.into_inner()
743    }
744}
745
746/// A response wrapper that notifies after response has been sent.
747///
748/// Sometimes in [`dbus_interface`] method implemenations we need to do some other work after the
749/// response has been sent off. This wrapper type allows us to do that. Instead of returning your
750/// intended response type directly, wrap it in this type and return it from your method. The
751/// returned `EventListener` from `new` method will be notified when the response has been sent.
752///
753/// A typical use case is sending off signals after the response has been sent. The easiest way to
754/// do that is to spawn a task from the method that sends the signal but only after being notified
755/// of the response dispatch.
756///
757/// # Caveats
758///
759/// The notification indicates that the response has been sent off, not that destination peer has
760/// received it. That can only be guaranteed for a peer-to-peer connection.
761///
762/// [`dbus_interface`]: crate::dbus_interface
763#[derive(Debug)]
764pub struct ResponseDispatchNotifier<R> {
765    response: R,
766    event: Option<Event>,
767}
768
769impl<R> ResponseDispatchNotifier<R> {
770    /// Create a new `NotifyResponse`.
771    pub fn new(response: R) -> (Self, EventListener) {
772        let event = Event::new();
773        let listener = event.listen();
774        (
775            Self {
776                response,
777                event: Some(event),
778            },
779            listener,
780        )
781    }
782}
783
784impl<R> Serialize for ResponseDispatchNotifier<R>
785where
786    R: Serialize,
787{
788    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
789    where
790        S: serde::Serializer,
791    {
792        self.response.serialize(serializer)
793    }
794}
795
796impl<R> Type for ResponseDispatchNotifier<R>
797where
798    R: Type,
799{
800    fn signature() -> Signature<'static> {
801        R::signature()
802    }
803}
804
805impl<T> Drop for ResponseDispatchNotifier<T> {
806    fn drop(&mut self) {
807        if let Some(event) = self.event.take() {
808            event.notify(usize::MAX);
809        }
810    }
811}