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