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