zbus/object_server/interface/
mod.rs

1mod dispatch_result;
2pub use dispatch_result::*;
3mod interface_ref;
4pub use interface_ref::*;
5mod interface_deref;
6pub use interface_deref::*;
7
8use std::{
9    any::{Any, TypeId},
10    collections::HashMap,
11    fmt::{self, Write},
12    sync::Arc,
13};
14
15use async_trait::async_trait;
16use zbus_names::{InterfaceName, MemberName};
17use zvariant::{OwnedValue, Value};
18
19use crate::{
20    async_lock::RwLock,
21    fdo,
22    message::{self, Header, Message},
23    object_server::SignalEmitter,
24    Connection, ObjectServer,
25};
26
27/// This trait is used to dispatch messages to an interface instance.
28///
29/// This trait should be treated as an unstable API and compatibility may break in minor
30/// version bumps. Because of this and other reasons, it is not recommended to manually implement
31/// this trait. The [`crate::interface`] macro implements it for you.
32///
33/// If you have an advanced use case where `interface` is inadequate, consider using
34/// [`crate::MessageStream`] or [`crate::blocking::MessageIterator`] instead.
35#[async_trait]
36pub trait Interface: Any + Send + Sync {
37    /// Return the name of the interface. Ex: "org.foo.MyInterface"
38    fn name() -> InterfaceName<'static>
39    where
40        Self: Sized;
41
42    /// Whether each method call will be handled from a different spawned task.
43    ///
44    /// Note: When methods are called from separate tasks, they may not be run in the order in which
45    /// they were called.
46    fn spawn_tasks_for_methods(&self) -> bool {
47        true
48    }
49
50    /// Get a property value. Returns `None` if the property doesn't exist.
51    ///
52    /// Note: The header parameter will be None when the getter is not being called as part
53    /// of D-Bus communication (for example, when it is called as part of initial object setup,
54    /// before it is registered on the bus, or when we manually send out property changed
55    /// notifications).
56    async fn get(
57        &self,
58        property_name: &str,
59        server: &ObjectServer,
60        connection: &Connection,
61        header: Option<&message::Header<'_>>,
62        emitter: &SignalEmitter<'_>,
63    ) -> Option<fdo::Result<OwnedValue>>;
64
65    /// Return all the properties.
66    async fn get_all(
67        &self,
68        object_server: &ObjectServer,
69        connection: &Connection,
70        header: Option<&message::Header<'_>>,
71        emitter: &SignalEmitter<'_>,
72    ) -> fdo::Result<HashMap<String, OwnedValue>>;
73
74    /// Set a property value.
75    ///
76    /// Return [`DispatchResult::NotFound`] if the property doesn't exist, or
77    /// [`DispatchResult::RequiresMut`] if `set_mut` should be used instead. The default
78    /// implementation just returns `RequiresMut`.
79    fn set<'call>(
80        &'call self,
81        property_name: &'call str,
82        value: &'call Value<'_>,
83        object_server: &'call ObjectServer,
84        connection: &'call Connection,
85        header: Option<&'call message::Header<'_>>,
86        emitter: &'call SignalEmitter<'_>,
87    ) -> DispatchResult<'call> {
88        let _ = (
89            property_name,
90            value,
91            object_server,
92            connection,
93            header,
94            emitter,
95        );
96        DispatchResult::RequiresMut
97    }
98
99    /// Set a property value.
100    ///
101    /// Returns `None` if the property doesn't exist.
102    ///
103    /// This will only be invoked if `set` returned `RequiresMut`.
104    async fn set_mut(
105        &mut self,
106        property_name: &str,
107        value: &Value<'_>,
108        object_server: &ObjectServer,
109        connection: &Connection,
110        header: Option<&Header<'_>>,
111        emitter: &SignalEmitter<'_>,
112    ) -> Option<fdo::Result<()>>;
113
114    /// Call a method.
115    ///
116    /// Return [`DispatchResult::NotFound`] if the method doesn't exist, or
117    /// [`DispatchResult::RequiresMut`] if `call_mut` should be used instead.
118    ///
119    /// It is valid, though inefficient, for this to always return `RequiresMut`.
120    fn call<'call>(
121        &'call self,
122        server: &'call ObjectServer,
123        connection: &'call Connection,
124        msg: &'call Message,
125        name: MemberName<'call>,
126    ) -> DispatchResult<'call>;
127
128    /// Call a `&mut self` method.
129    ///
130    /// This will only be invoked if `call` returned `RequiresMut`.
131    fn call_mut<'call>(
132        &'call mut self,
133        server: &'call ObjectServer,
134        connection: &'call Connection,
135        msg: &'call Message,
136        name: MemberName<'call>,
137    ) -> DispatchResult<'call>;
138
139    /// Write introspection XML to the writer, with the given indentation level.
140    fn introspect_to_writer(&self, writer: &mut dyn Write, level: usize);
141}
142
143/// A type for a reference-counted Interface trait-object, with associated run-time details and a
144/// manual Debug impl.
145#[derive(Clone)]
146pub(crate) struct ArcInterface {
147    pub instance: Arc<RwLock<dyn Interface>>,
148    pub spawn_tasks_for_methods: bool,
149}
150
151impl ArcInterface {
152    pub fn new<I>(iface: I) -> Self
153    where
154        I: Interface,
155    {
156        let spawn_tasks_for_methods = iface.spawn_tasks_for_methods();
157        Self {
158            instance: Arc::new(RwLock::new(iface)),
159            spawn_tasks_for_methods,
160        }
161    }
162}
163
164impl fmt::Debug for ArcInterface {
165    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166        f.debug_struct("Arc<RwLock<dyn Interface>>")
167            .finish_non_exhaustive()
168    }
169}
170
171// Note: while it is possible to implement this without `unsafe`, it currently requires a helper
172// trait with a blanket impl that creates `dyn Any` refs.  It's simpler (and more performant) to
173// just check the type ID and do the downcast ourself.
174//
175// See https://github.com/rust-lang/rust/issues/65991 for a rustc feature that will make it
176// possible to get a `dyn Any` ref directly from a `dyn Interface` ref; once that is stable, we can
177// remove this unsafe code.
178impl dyn Interface {
179    /// Return Any of self
180    pub(crate) fn downcast_ref<T: Any>(&self) -> Option<&T> {
181        if <dyn Interface as Any>::type_id(self) == TypeId::of::<T>() {
182            // SAFETY: If type ID matches, it means object is of type T
183            Some(unsafe { &*(self as *const dyn Interface as *const T) })
184        } else {
185            None
186        }
187    }
188
189    /// Return Any of self
190    pub(crate) fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
191        if <dyn Interface as Any>::type_id(self) == TypeId::of::<T>() {
192            // SAFETY: If type ID matches, it means object is of type T
193            Some(unsafe { &mut *(self as *mut dyn Interface as *mut T) })
194        } else {
195            None
196        }
197    }
198}