Skip to main content

zbus/object_server/interface/
dispatch_result.rs

1use std::{future::Future, pin::Pin};
2
3use zbus::message::Flags;
4use zvariant::DynamicType;
5
6use crate::{Connection, Result, fdo, message::Message};
7use tracing::trace;
8
9/// A helper type returned by [`Interface`](`crate::object_server::Interface`) callbacks.
10#[deprecated(since = "5.15.0", note = "Use `DispatchResult2` instead.")]
11pub enum DispatchResult<'a> {
12    /// This interface does not support the given method.
13    NotFound,
14
15    /// Retry with [Interface::call_mut](`crate::object_server::Interface::call_mut).
16    ///
17    /// This is equivalent to NotFound if returned by call_mut.
18    RequiresMut,
19
20    /// The method was found and will be completed by running this Future.
21    Async(Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>),
22}
23
24#[allow(deprecated)]
25impl<'a> DispatchResult<'a> {
26    /// Helper for creating the Async variant.
27    pub fn new_async<F, T, E>(conn: &'a Connection, msg: &'a Message, f: F) -> Self
28    where
29        F: Future<Output = ::std::result::Result<T, E>> + Send + 'a,
30        T: serde::Serialize + DynamicType + Send + Sync,
31        E: zbus::DBusError + Send,
32    {
33        DispatchResult::Async(Box::pin(async move {
34            let hdr = msg.header();
35            let ret = f.await;
36            if !hdr.primary().flags().contains(Flags::NoReplyExpected) {
37                match ret {
38                    Ok(r) => conn.reply(&hdr, &r).await,
39                    Err(e) => conn.reply_dbus_error(&hdr, e).await,
40                }
41                .map(|_seq| ())
42            } else {
43                trace!("No reply expected for {:?} by the caller.", msg);
44                Ok(())
45            }
46        }))
47    }
48}
49
50/// A helper type returned by [`Interface`](`crate::object_server::Interface`) callbacks.
51///
52/// Unlike [`DispatchResult`], the [`Async`](DispatchResult2::Async) variant uses
53/// [`fdo::Result`] so that D-Bus error names are preserved without nesting through
54/// intermediate [`crate::Error`] conversions.
55///
56/// This is an unstable type — compatibility may break in minor version bumps.
57pub enum DispatchResult2<'a> {
58    /// This interface does not support the given method.
59    NotFound,
60
61    /// Retry with [`Interface::call_mut`](`crate::object_server::Interface::call_mut`).
62    ///
63    /// This is equivalent to NotFound if returned by call_mut.
64    RequiresMut,
65
66    /// The method was found and will be completed by running this Future.
67    Async(Pin<Box<dyn Future<Output = fdo::Result<()>> + Send + 'a>>),
68}
69
70impl<'a> DispatchResult2<'a> {
71    /// Helper for creating the Async variant.
72    pub fn new_async<F, T, E>(conn: &'a Connection, msg: &'a Message, f: F) -> Self
73    where
74        F: Future<Output = ::std::result::Result<T, E>> + Send + 'a,
75        T: serde::Serialize + DynamicType + Send + Sync,
76        E: zbus::DBusError + Send,
77    {
78        DispatchResult2::Async(Box::pin(async move {
79            let hdr = msg.header();
80            let ret = f.await;
81            if !hdr.primary().flags().contains(Flags::NoReplyExpected) {
82                match ret {
83                    Ok(r) => conn.reply(&hdr, &r).await,
84                    Err(e) => conn.reply_dbus_error(&hdr, e).await,
85                }
86                .map(|_seq| ())
87                .map_err(|e| fdo::Error::Failed(e.to_string()))
88            } else {
89                trace!("No reply expected for {:?} by the caller.", msg);
90                Ok(())
91            }
92        }))
93    }
94}