zbus/blocking/object_server.rs
1//! The object server API.
2
3use zvariant::ObjectPath;
4
5use crate::{
6 object_server::{Interface, InterfaceDeref, InterfaceDerefMut, SignalEmitter},
7 utils::block_on,
8 Error, Result,
9};
10
11/// Wrapper over an interface, along with its corresponding `SignalEmitter`
12/// instance. A reference to the underlying interface may be obtained via
13/// [`InterfaceRef::get`] and [`InterfaceRef::get_mut`].
14pub struct InterfaceRef<I> {
15 azync: crate::object_server::InterfaceRef<I>,
16}
17
18impl<I> InterfaceRef<I>
19where
20 I: 'static,
21{
22 /// Get a reference to the underlying interface.
23 ///
24 /// **WARNING:** If methods (e.g property setters) in `ObjectServer` require `&mut self`
25 /// `ObjectServer` will not be able to access the interface in question until all references
26 /// of this method are dropped; it is highly recommended that the scope of the interface
27 /// returned is restricted.
28 pub fn get(&self) -> InterfaceDeref<'_, I> {
29 block_on(self.azync.get())
30 }
31
32 /// Get a reference to the underlying interface.
33 ///
34 /// **WARNING:** Since the `ObjectServer` will not be able to access the interface in question
35 /// until the return value of this method is dropped, it is highly recommended that the scope
36 /// of the interface returned is restricted.
37 ///
38 /// # Errors
39 ///
40 /// If the interface at this instance's path is not valid, an `Error::InterfaceNotFound` error
41 /// is returned.
42 ///
43 /// # Examples
44 ///
45 /// ```no_run
46 /// # use std::error::Error;
47 /// # use async_io::block_on;
48 /// # use zbus::{blocking::Connection, interface};
49 ///
50 /// struct MyIface(u32);
51 ///
52 /// #[interface(name = "org.myiface.MyIface")]
53 /// impl MyIface {
54 /// #[zbus(property)]
55 /// fn count(&self) -> u32 {
56 /// self.0
57 /// }
58 /// }
59 /// // Set up connection and object_server etc here and then in another part of the code:
60 /// #
61 /// # let connection = Connection::session()?;
62 /// #
63 /// # let path = "/org/zbus/path";
64 /// # connection.object_server().at(path, MyIface(22))?;
65 /// let object_server = connection.object_server();
66 /// let iface_ref = object_server.interface::<_, MyIface>(path)?;
67 /// let mut iface = iface_ref.get_mut();
68 /// iface.0 = 42;
69 /// block_on(iface.count_changed(iface_ref.signal_emitter()))?;
70 /// #
71 /// # Ok::<_, Box<dyn Error + Send + Sync>>(())
72 /// ```
73 pub fn get_mut(&self) -> InterfaceDerefMut<'_, I> {
74 block_on(self.azync.get_mut())
75 }
76
77 pub fn signal_emitter(&self) -> &SignalEmitter<'static> {
78 self.azync.signal_emitter()
79 }
80}
81
82/// A blocking wrapper of [`crate::ObjectServer`].
83///
84/// # Example
85///
86/// This example exposes the `org.myiface.Example.Quit` method on the `/org/zbus/path`
87/// path.
88///
89/// ```no_run
90/// # use std::error::Error;
91/// use zbus::{blocking::Connection, interface};
92/// use event_listener::{Event, Listener};
93///
94/// struct Example {
95/// // Interfaces are owned by the ObjectServer. They can have
96/// // `&mut self` methods.
97/// quit_event: Event,
98/// }
99///
100/// impl Example {
101/// fn new(quit_event: Event) -> Self {
102/// Self { quit_event }
103/// }
104/// }
105///
106/// #[interface(name = "org.myiface.Example")]
107/// impl Example {
108/// // This will be the "Quit" D-Bus method.
109/// fn quit(&mut self) {
110/// self.quit_event.notify(1);
111/// }
112///
113/// // See `interface` documentation to learn
114/// // how to expose properties & signals as well.
115/// }
116///
117/// let connection = Connection::session()?;
118///
119/// let quit_event = Event::new();
120/// let quit_listener = quit_event.listen();
121/// let interface = Example::new(quit_event);
122/// connection
123/// .object_server()
124/// .at("/org/zbus/path", interface)?;
125///
126/// quit_listener.wait();
127/// # Ok::<_, Box<dyn Error + Send + Sync>>(())
128/// ```
129#[derive(Debug, Clone)]
130pub struct ObjectServer {
131 azync: crate::ObjectServer,
132}
133
134impl ObjectServer {
135 /// Create a new D-Bus `ObjectServer`.
136 pub(crate) fn new(conn: &crate::Connection) -> Self {
137 Self {
138 azync: conn.object_server().clone(),
139 }
140 }
141
142 /// Register a D-Bus [`Interface`] at a given path (see the example above).
143 ///
144 /// Typically you'd want your interfaces to be registered immediately after the associated
145 /// connection is established and therefore use
146 /// [`zbus::blocking::connection::Builder::serve_at`] instead. However, there are
147 /// situations where you'd need to register interfaces dynamically and that's where this
148 /// method becomes useful.
149 ///
150 /// If the interface already exists at this path, returns false.
151 ///
152 /// [`Interface`]: trait.Interface.html
153 pub fn at<'p, P, I>(&self, path: P, iface: I) -> Result<bool>
154 where
155 I: Interface,
156 P: TryInto<ObjectPath<'p>>,
157 P::Error: Into<Error>,
158 {
159 block_on(self.azync.at(path, iface))
160 }
161
162 /// Unregister a D-Bus [`Interface`] at a given path.
163 ///
164 /// If there are no more interfaces left at that path, destroys the object as well.
165 /// Returns whether the object was destroyed.
166 ///
167 /// [`Interface`]: trait.Interface.html
168 pub fn remove<'p, I, P>(&self, path: P) -> Result<bool>
169 where
170 I: Interface,
171 P: TryInto<ObjectPath<'p>>,
172 P::Error: Into<Error>,
173 {
174 block_on(self.azync.remove::<I, P>(path))
175 }
176
177 /// Get the interface at the given path.
178 ///
179 /// # Errors
180 ///
181 /// If the interface is not registered at the given path, an `Error::InterfaceNotFound` error is
182 /// returned.
183 ///
184 /// # Examples
185 ///
186 /// The typical use of this is to emit signals outside of a dispatched handler:
187 ///
188 /// ```no_run
189 /// # use std::error::Error;
190 /// # use zbus::block_on;
191 /// # use zbus::{
192 /// # object_server::SignalEmitter,
193 /// # blocking::Connection,
194 /// # interface,
195 /// # };
196 /// #
197 /// struct MyIface;
198 /// #[interface(name = "org.myiface.MyIface")]
199 /// impl MyIface {
200 /// #[zbus(signal)]
201 /// async fn emit_signal(emitter: &SignalEmitter<'_>) -> zbus::Result<()>;
202 /// }
203 ///
204 /// # let connection = Connection::session()?;
205 /// #
206 /// # let path = "/org/zbus/path";
207 /// # connection.object_server().at(path, MyIface)?;
208 /// let iface_ref = connection
209 /// .object_server()
210 /// .interface::<_, MyIface>(path)?;
211 /// block_on(MyIface::emit_signal(iface_ref.signal_emitter()))?;
212 /// #
213 /// #
214 /// # Ok::<_, Box<dyn Error + Send + Sync>>(())
215 /// ```
216 pub fn interface<'p, P, I>(&self, path: P) -> Result<InterfaceRef<I>>
217 where
218 I: Interface,
219 P: TryInto<ObjectPath<'p>>,
220 P::Error: Into<Error>,
221 {
222 Ok(InterfaceRef {
223 azync: block_on(self.azync.interface(path))?,
224 })
225 }
226
227 /// Get a reference to the underlying async ObjectServer.
228 pub fn inner(&self) -> &crate::ObjectServer {
229 &self.azync
230 }
231
232 /// Get the underlying async ObjectServer, consuming `self`.
233 pub fn into_inner(self) -> crate::ObjectServer {
234 self.azync
235 }
236}
237
238impl From<crate::ObjectServer> for ObjectServer {
239 fn from(azync: crate::ObjectServer) -> Self {
240 Self { azync }
241 }
242}