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 = Event::new();
773 let listener: EventListener = 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: Event) = self.event.take() {
808 event.notify(usize::MAX);
809 }
810 }
811}
812