| 1 | #![deny (rust_2018_idioms)] |
| 2 | #![doc ( |
| 3 | html_logo_url = "https://raw.githubusercontent.com/dbus2/zbus/9f7a90d2b594ddc48b7a5f39fda5e00cd56a7dfb/logo.png" |
| 4 | )] |
| 5 | #![doc = include_str!("../README.md" )] |
| 6 | #![doc (test(attr( |
| 7 | warn(unused), |
| 8 | deny(warnings), |
| 9 | allow(dead_code), |
| 10 | // W/o this, we seem to get some bogus warning about `extern crate zbus`. |
| 11 | allow(unused_extern_crates), |
| 12 | )))] |
| 13 | |
| 14 | use proc_macro::TokenStream; |
| 15 | use syn::{ |
| 16 | parse_macro_input, punctuated::Punctuated, DeriveInput, ItemImpl, ItemTrait, Meta, Token, |
| 17 | }; |
| 18 | |
| 19 | mod error; |
| 20 | mod iface; |
| 21 | mod proxy; |
| 22 | mod utils; |
| 23 | |
| 24 | /// Attribute macro for defining D-Bus proxies (using [`zbus::Proxy`] and |
| 25 | /// [`zbus::blocking::Proxy`]). |
| 26 | /// |
| 27 | /// The macro must be applied on a `trait T`. Two matching `impl T` will provide an asynchronous |
| 28 | /// Proxy implementation, named `TraitNameProxy` and a blocking one, named `TraitNameProxyBlocking`. |
| 29 | /// The proxy instances can be created with the associated `new()` or `builder()` methods. The |
| 30 | /// former doesn't take any argument and uses the default service name and path. The later allows |
| 31 | /// you to specify non-default proxy arguments. |
| 32 | /// |
| 33 | /// The following attributes are supported: |
| 34 | /// |
| 35 | /// * `interface` - the name of the D-Bus interface this proxy is for. |
| 36 | /// |
| 37 | /// * `default_service` - the default service this proxy should connect to. |
| 38 | /// |
| 39 | /// * `default_path` - The default object path the method calls will be sent on and signals will be |
| 40 | /// sent for by the target service. |
| 41 | /// |
| 42 | /// * `gen_async` - Whether or not to generate the asynchronous Proxy type. |
| 43 | /// |
| 44 | /// * `gen_blocking` - Whether or not to generate the blocking Proxy type. If set to `false`, the |
| 45 | /// asynchronous proxy type will take the name `TraitNameProxy` (i-e no `Async` prefix). |
| 46 | /// |
| 47 | /// * `async_name` - Specify the exact name of the asynchronous proxy type. |
| 48 | /// |
| 49 | /// * `blocking_name` - Specify the exact name of the blocking proxy type. |
| 50 | /// |
| 51 | /// * `assume_defaults` - whether to auto-generate values for `default_path` and `default_service` |
| 52 | /// if none are specified (default: `false`). `proxy` generates a warning if neither this |
| 53 | /// attribute nor one of the default values are specified. Please make sure to explicitly set |
| 54 | /// either this attribute or the default values, according to your needs. |
| 55 | /// |
| 56 | /// Each trait method will be expanded to call to the associated D-Bus remote interface. |
| 57 | /// |
| 58 | /// Trait methods accept `proxy` attributes: |
| 59 | /// |
| 60 | /// * `name` - override the D-Bus name (pascal case form by default) |
| 61 | /// |
| 62 | /// * `property` - expose the method as a property. If the method takes an argument, it must be a |
| 63 | /// setter, with a `set_` prefix. Otherwise, it's a getter. Additional sub-attributes exists to |
| 64 | /// control specific property behaviors: |
| 65 | /// * `emits_changed_signal` - specifies how property changes are signaled. Valid values are those |
| 66 | /// documented in [DBus specifications][dbus_emits_changed_signal]: |
| 67 | /// * `"true"` - (default) change signal is always emitted with the value included. This uses |
| 68 | /// the default caching behavior of the proxy, and generates a listener method for the change |
| 69 | /// signal. |
| 70 | /// * `"invalidates"` - change signal is emitted, but the value is not included in the signal. |
| 71 | /// This has the same behavior as `"true"`. |
| 72 | /// * `"const"` - property never changes, thus no signal is ever emitted for it. This uses the |
| 73 | /// default caching behavior of the proxy, but does not generate a listener method for the |
| 74 | /// change signal. |
| 75 | /// * `"false"` - change signal is not (guaranteed to be) emitted if the property changes. This |
| 76 | /// disables property value caching, and does not generate a listener method for the change |
| 77 | /// signal. |
| 78 | /// |
| 79 | /// * `signal` - declare a signal just like a D-Bus method. Read the [Signals](#signals) section |
| 80 | /// below for details. |
| 81 | /// |
| 82 | /// * `no_reply` - declare a method call that does not wait for a reply. |
| 83 | /// |
| 84 | /// * `no_autostart` - declare a method call that will not trigger the bus to automatically launch |
| 85 | /// the destination service if it is not already running. |
| 86 | /// |
| 87 | /// * `allow_interactive_auth` - declare a method call that is allowed to trigger an interactive |
| 88 | /// prompt for authorization or confirmation from the receiver. |
| 89 | /// |
| 90 | /// * `object` - methods that returns an [`ObjectPath`] can be annotated with the `object` attribute |
| 91 | /// to specify the proxy object to be constructed from the returned [`ObjectPath`]. |
| 92 | /// |
| 93 | /// * `async_object` - if the assumptions made by `object` attribute about naming of the |
| 94 | /// asynchronous proxy type, don't fit your bill, you can use this to specify its exact name. |
| 95 | /// |
| 96 | /// * `blocking_object` - if the assumptions made by `object` attribute about naming of the blocking |
| 97 | /// proxy type, don't fit your bill, you can use this to specify its exact name. |
| 98 | /// |
| 99 | /// NB: Any doc comments provided shall be appended to the ones added by the macro. |
| 100 | /// |
| 101 | /// # Signals |
| 102 | /// |
| 103 | /// For each signal method declared, this macro will provide a method, named `receive_<method_name>` |
| 104 | /// to create a [`zbus::SignalStream`] ([`zbus::blocking::SignalIterator`] for the blocking proxy) |
| 105 | /// wrapper, named `<SignalName>Stream` (`<SignalName>Iterator` for the blocking proxy) that yield |
| 106 | /// a [`zbus::message::Message`] wrapper, named `<SignalName>`. This wrapper provides type safe |
| 107 | /// access to the signal arguments. It also implements `Deref<Target = Message>` to allow easy |
| 108 | /// access to the underlying [`zbus::message::Message`]. |
| 109 | /// |
| 110 | /// # Example |
| 111 | /// |
| 112 | /// ```no_run |
| 113 | /// # use std::error::Error; |
| 114 | /// use zbus_macros::proxy; |
| 115 | /// use zbus::{blocking::Connection, Result, fdo, zvariant::Value}; |
| 116 | /// use futures_util::stream::StreamExt; |
| 117 | /// use async_io::block_on; |
| 118 | /// |
| 119 | /// #[proxy( |
| 120 | /// interface = "org.test.SomeIface" , |
| 121 | /// default_service = "org.test.SomeService" , |
| 122 | /// default_path = "/org/test/SomeObject" |
| 123 | /// )] |
| 124 | /// trait SomeIface { |
| 125 | /// fn do_this(&self, with: &str, some: u32, arg: &Value<'_>) -> Result<bool>; |
| 126 | /// |
| 127 | /// #[zbus(property)] |
| 128 | /// fn a_property(&self) -> fdo::Result<String>; |
| 129 | /// |
| 130 | /// #[zbus(property)] |
| 131 | /// fn set_a_property(&self, a_property: &str) -> fdo::Result<()>; |
| 132 | /// |
| 133 | /// #[zbus(signal)] |
| 134 | /// fn some_signal(&self, arg1: &str, arg2: u32) -> fdo::Result<()>; |
| 135 | /// |
| 136 | /// #[zbus(object = "SomeOtherIface" , blocking_object = "SomeOtherInterfaceBlock" )] |
| 137 | /// // The method will return a `SomeOtherIfaceProxy` or `SomeOtherIfaceProxyBlock`, depending |
| 138 | /// // on whether it is called on `SomeIfaceProxy` or `SomeIfaceProxyBlocking`, respectively. |
| 139 | /// // |
| 140 | /// // NB: We explicitly specified the exact name of the blocking proxy type. If we hadn't, |
| 141 | /// // `SomeOtherIfaceProxyBlock` would have been assumed and expected. We could also specify |
| 142 | /// // the specific name of the asynchronous proxy types, using the `async_object` attribute. |
| 143 | /// fn some_method(&self, arg1: &str); |
| 144 | /// } |
| 145 | /// |
| 146 | /// #[proxy( |
| 147 | /// interface = "org.test.SomeOtherIface" , |
| 148 | /// default_service = "org.test.SomeOtherService" , |
| 149 | /// blocking_name = "SomeOtherInterfaceBlock" , |
| 150 | /// )] |
| 151 | /// trait SomeOtherIface {} |
| 152 | /// |
| 153 | /// let connection = Connection::session()?; |
| 154 | /// // Use `builder` to override the default arguments, `new` otherwise. |
| 155 | /// let proxy = SomeIfaceProxyBlocking::builder(&connection) |
| 156 | /// .destination("org.another.Service" )? |
| 157 | /// .cache_properties(zbus::CacheProperties::No) |
| 158 | /// .build()?; |
| 159 | /// let _ = proxy.do_this("foo" , 32, &Value::new(true)); |
| 160 | /// let _ = proxy.set_a_property("val" ); |
| 161 | /// |
| 162 | /// let signal = proxy.receive_some_signal()?.next().unwrap(); |
| 163 | /// let args = signal.args()?; |
| 164 | /// println!("arg1: {}, arg2: {}" , args.arg1(), args.arg2()); |
| 165 | /// |
| 166 | /// // Now the same again, but asynchronous. |
| 167 | /// block_on(async move { |
| 168 | /// let proxy = SomeIfaceProxy::builder(&connection.into()) |
| 169 | /// .cache_properties(zbus::CacheProperties::No) |
| 170 | /// .build() |
| 171 | /// .await |
| 172 | /// .unwrap(); |
| 173 | /// let _ = proxy.do_this("foo" , 32, &Value::new(true)).await; |
| 174 | /// let _ = proxy.set_a_property("val" ).await; |
| 175 | /// |
| 176 | /// let signal = proxy.receive_some_signal().await?.next().await.unwrap(); |
| 177 | /// let args = signal.args()?; |
| 178 | /// println!("arg1: {}, arg2: {}" , args.arg1(), args.arg2()); |
| 179 | /// |
| 180 | /// Ok::<(), zbus::Error>(()) |
| 181 | /// })?; |
| 182 | /// |
| 183 | /// # Ok::<_, Box<dyn Error + Send + Sync>>(()) |
| 184 | /// ``` |
| 185 | /// |
| 186 | /// [`zbus_polkit`] is a good example of how to bind a real D-Bus API. |
| 187 | /// |
| 188 | /// [`zbus_polkit`]: https://docs.rs/zbus_polkit/1.0.0/zbus_polkit/policykit1/index.html |
| 189 | /// [`zbus::Proxy`]: https://docs.rs/zbus/latest/zbus/proxy/struct.Proxy.html |
| 190 | /// [`zbus::message::Message`]: https://docs.rs/zbus/latest/zbus/message/struct.Message.html |
| 191 | /// [`zbus::blocking::Proxy`]: https://docs.rs/zbus/latest/zbus/blocking/proxy/struct.Proxy.html |
| 192 | /// [`zbus::SignalStream`]: https://docs.rs/zbus/latest/zbus/proxy/struct.SignalStream.html |
| 193 | /// [`zbus::blocking::SignalIterator`]: https://docs.rs/zbus/latest/zbus/blocking/proxy/struct.SignalIterator.html |
| 194 | /// [`ObjectPath`]: https://docs.rs/zvariant/latest/zvariant/struct.ObjectPath.html |
| 195 | /// [dbus_emits_changed_signal]: https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format |
| 196 | #[proc_macro_attribute ] |
| 197 | pub fn proxy (attr: TokenStream, item: TokenStream) -> TokenStream { |
| 198 | let args: Punctuated = parse_macro_input!(attr with Punctuated<Meta, Token![,]>::parse_terminated); |
| 199 | let input: ItemTrait = parse_macro_input!(item as ItemTrait); |
| 200 | proxyTokenStream::expand::<proxy::TraitAttributes, proxy::MethodAttributes>(args, input) |
| 201 | .unwrap_or_else(|err: Error| err.to_compile_error()) |
| 202 | .into() |
| 203 | } |
| 204 | |
| 205 | #[deprecated = "Use `#[proxy(...)]` proc macro with `#[zbus(...)]` item attributes instead." ] |
| 206 | #[proc_macro_attribute ] |
| 207 | pub fn dbus_proxy (attr: TokenStream, item: TokenStream) -> TokenStream { |
| 208 | let args: Punctuated = parse_macro_input!(attr with Punctuated<Meta, Token![,]>::parse_terminated); |
| 209 | let input: ItemTrait = parse_macro_input!(item as ItemTrait); |
| 210 | proxyTokenStream::expand::<proxy::old::TraitAttributes, proxy::old::MethodAttributes>(args, input) |
| 211 | .unwrap_or_else(|err: Error| err.to_compile_error()) |
| 212 | .into() |
| 213 | } |
| 214 | |
| 215 | /// Attribute macro for implementing a D-Bus interface. |
| 216 | /// |
| 217 | /// The macro must be applied on an `impl T`. All methods will be exported, either as methods, |
| 218 | /// properties or signal depending on the item attributes. It will implement the [`Interface`] trait |
| 219 | /// `for T` on your behalf, to handle the message dispatching and introspection support. |
| 220 | /// |
| 221 | /// The trait accepts the `interface` attributes: |
| 222 | /// |
| 223 | /// * `name` - the D-Bus interface name |
| 224 | /// |
| 225 | /// * `spawn` - Controls the spawning of tasks for method calls. By default, `true`, allowing zbus |
| 226 | /// to spawn a separate task for each method call. This default behavior can lead to methods being |
| 227 | /// handled out of their received order, which might not always align with expected or desired |
| 228 | /// behavior. |
| 229 | /// |
| 230 | /// - **When True (Default):** Suitable for interfaces where method calls are independent of each |
| 231 | /// other or can be processed asynchronously without strict ordering. In scenarios where a client |
| 232 | /// must wait for a reply before making further dependent calls, this default behavior is |
| 233 | /// appropriate. |
| 234 | /// |
| 235 | /// - **When False:** Use this setting to ensure methods are handled in the order they are |
| 236 | /// received, which is crucial for interfaces requiring sequential processing of method calls. |
| 237 | /// However, care must be taken to avoid making D-Bus method calls from within your interface |
| 238 | /// methods when this setting is false, as it may lead to deadlocks under certain conditions. |
| 239 | /// |
| 240 | /// * `proxy` - If specified, a proxy type will also be generated for the interface. This attribute |
| 241 | /// supports all the [`macro@proxy`]-specific sub-attributes (e.g `gen_async`). The common |
| 242 | /// sub-attributes (e.g `name`) are automatically forworded to the [`macro@proxy`] macro. |
| 243 | /// |
| 244 | /// The methods accepts the `interface` attributes: |
| 245 | /// |
| 246 | /// * `name` - override the D-Bus name (pascal case form of the method by default) |
| 247 | /// |
| 248 | /// * `property` - expose the method as a property. If the method takes an argument, it must be a |
| 249 | /// setter, with a `set_` prefix. Otherwise, it's a getter. If it may fail, a property method must |
| 250 | /// return `zbus::fdo::Result`. An additional sub-attribute exists to control the emission of |
| 251 | /// signals on changes to the property: |
| 252 | /// * `emits_changed_signal` - specifies how property changes are signaled. Valid values are those |
| 253 | /// documented in [DBus specifications][dbus_emits_changed_signal]: |
| 254 | /// * `"true"` - (default) the change signal is always emitted when the property's setter is |
| 255 | /// called. The value of the property is included in the signal. |
| 256 | /// * `"invalidates"` - the change signal is emitted, but the value is not included in the |
| 257 | /// signal. |
| 258 | /// * `"const"` - the property never changes, thus no signal is ever emitted for it. |
| 259 | /// * `"false"` - the change signal is not emitted if the property changes. |
| 260 | |
| 261 | /// * `signal` - the method is a "signal". It must be a method declaration (without body). Its code |
| 262 | /// block will be expanded to emit the signal from the object path associated with the interface |
| 263 | /// instance. |
| 264 | /// |
| 265 | /// You can call a signal method from a an interface method, or from an [`ObjectServer::with`] |
| 266 | /// function. |
| 267 | /// |
| 268 | /// * `out_args` - When returning multiple values from a method, naming the out arguments become |
| 269 | /// important. You can use `out_args` to specify their names. |
| 270 | /// |
| 271 | /// * `proxy` - Use this to specify the [`macro@proxy`]-specific method sub-attributes (e.g |
| 272 | /// `object`). The common sub-attributes (e.g `name`) are automatically forworded to the |
| 273 | /// [`macro@proxy`] macro. |
| 274 | /// |
| 275 | /// In such case, your method must return a tuple containing |
| 276 | /// your out arguments, in the same order as passed to `out_args`. |
| 277 | /// |
| 278 | /// The `struct_return` attribute (from zbus 1.x) is no longer supported. If you want to return a |
| 279 | /// single structure from a method, declare it to return a tuple containing either a named structure |
| 280 | /// or a nested tuple. |
| 281 | /// |
| 282 | /// Note: a `<property_name_in_snake_case>_changed` method is generated for each property: this |
| 283 | /// method emits the "PropertiesChanged" signal for the associated property. The setter (if it |
| 284 | /// exists) will automatically call this method. For instance, a property setter named `set_foo` |
| 285 | /// will be called to set the property "Foo", and will emit the "PropertiesChanged" signal with the |
| 286 | /// new value for "Foo". Other changes to the "Foo" property can be signaled manually with the |
| 287 | /// generated `foo_changed` method. In addition, a `<property_name_in_snake_case>_invalidated` |
| 288 | /// method is also generated that much like `_changed` method, emits a "PropertyChanged" signal |
| 289 | /// but does not send over the new value of the property along with it. It is usually best to avoid |
| 290 | /// using this since it will force all interested peers to fetch the new value and hence result in |
| 291 | /// excess traffic on the bus. |
| 292 | /// |
| 293 | /// The method arguments support the following `zbus` attributes: |
| 294 | /// |
| 295 | /// * `object_server` - This marks the method argument to receive a reference to the |
| 296 | /// [`ObjectServer`] this method was called by. |
| 297 | /// * `connection` - This marks the method argument to receive a reference to the [`Connection`] on |
| 298 | /// which the method call was received. |
| 299 | /// * `header` - This marks the method argument to receive the message header associated with the |
| 300 | /// D-Bus method call being handled. |
| 301 | /// * `signal_context` - This marks the method argument to receive a [`SignalContext`] instance, |
| 302 | /// which is needed for emitting signals the easy way. |
| 303 | /// |
| 304 | /// # Example |
| 305 | /// |
| 306 | /// ``` |
| 307 | /// # use std::error::Error; |
| 308 | /// use zbus_macros::interface; |
| 309 | /// use zbus::{ObjectServer, object_server::SignalContext, message::Header}; |
| 310 | /// |
| 311 | /// struct Example { |
| 312 | /// _some_data: String, |
| 313 | /// } |
| 314 | /// |
| 315 | /// #[interface(name = "org.myservice.Example" )] |
| 316 | /// impl Example { |
| 317 | /// // "Quit" method. A method may throw errors. |
| 318 | /// async fn quit( |
| 319 | /// &self, |
| 320 | /// #[zbus(header)] |
| 321 | /// hdr: Header<'_>, |
| 322 | /// #[zbus(signal_context)] |
| 323 | /// ctxt: SignalContext<'_>, |
| 324 | /// #[zbus(object_server)] |
| 325 | /// _server: &ObjectServer, |
| 326 | /// ) -> zbus::fdo::Result<()> { |
| 327 | /// let path = hdr.path().unwrap(); |
| 328 | /// let msg = format!("You are leaving me on the {} path?" , path); |
| 329 | /// Example::bye(&ctxt, &msg).await?; |
| 330 | /// |
| 331 | /// // Do some asynchronous tasks before quitting.. |
| 332 | /// |
| 333 | /// Ok(()) |
| 334 | /// } |
| 335 | /// |
| 336 | /// // "TheAnswer" property (note: the "name" attribute), with its associated getter. |
| 337 | /// // A `the_answer_changed` method has also been generated to emit the |
| 338 | /// // "PropertiesChanged" signal for this property. |
| 339 | /// #[zbus(property, name = "TheAnswer" )] |
| 340 | /// fn answer(&self) -> u32 { |
| 341 | /// 2 * 3 * 7 |
| 342 | /// } |
| 343 | /// |
| 344 | /// // "IFail" property with its associated getter. |
| 345 | /// // An `i_fail_changed` method has also been generated to emit the |
| 346 | /// // "PropertiesChanged" signal for this property. |
| 347 | /// #[zbus(property)] |
| 348 | /// fn i_fail(&self) -> zbus::fdo::Result<i32> { |
| 349 | /// Err(zbus::fdo::Error::UnknownProperty("IFail" .into())) |
| 350 | /// } |
| 351 | /// |
| 352 | /// // "Bye" signal (note: no implementation body). |
| 353 | /// #[zbus(signal)] |
| 354 | /// async fn bye(signal_ctxt: &SignalContext<'_>, message: &str) -> zbus::Result<()>; |
| 355 | /// |
| 356 | /// #[zbus(out_args("answer" , "question" ))] |
| 357 | /// fn meaning_of_life(&self) -> zbus::fdo::Result<(i32, String)> { |
| 358 | /// Ok((42, String::from("Meaning of life" ))) |
| 359 | /// } |
| 360 | /// } |
| 361 | /// |
| 362 | /// # Ok::<_, Box<dyn Error + Send + Sync>>(()) |
| 363 | /// ``` |
| 364 | /// |
| 365 | /// See also [`ObjectServer`] documentation to learn how to export an interface over a `Connection`. |
| 366 | /// |
| 367 | /// [`ObjectServer`]: https://docs.rs/zbus/latest/zbus/object_server/struct.ObjectServer.html |
| 368 | /// [`ObjectServer::with`]: https://docs.rs/zbus/latest/zbus/object_server/struct.ObjectServer.html#method.with |
| 369 | /// [`Connection`]: https://docs.rs/zbus/latest/zbus/connection/struct.Connection.html |
| 370 | /// [`Connection::emit_signal()`]: https://docs.rs/zbus/latest/zbus/connection/struct.Connection.html#method.emit_signal |
| 371 | /// [`SignalContext`]: https://docs.rs/zbus/latest/zbus/object_server/struct.SignalContext.html |
| 372 | /// [`Interface`]: https://docs.rs/zbus/latest/zbus/object_server/trait.Interface.html |
| 373 | /// [dbus_emits_changed_signal]: https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format |
| 374 | #[proc_macro_attribute ] |
| 375 | pub fn interface (attr: TokenStream, item: TokenStream) -> TokenStream { |
| 376 | let args: Punctuated = parse_macro_input!(attr with Punctuated<Meta, Token![,]>::parse_terminated); |
| 377 | let input: ItemImpl = parse_macro_input!(item as ItemImpl); |
| 378 | ifaceTokenStream::expand::<iface::ImplAttributes, iface::MethodAttributes>(args, input) |
| 379 | .unwrap_or_else(|err: Error| err.to_compile_error()) |
| 380 | .into() |
| 381 | } |
| 382 | |
| 383 | #[deprecated = "Use `#[interface(...)]` proc macro with `#[zbus(...)]` item attributes instead." ] |
| 384 | #[proc_macro_attribute ] |
| 385 | pub fn dbus_interface (attr: TokenStream, item: TokenStream) -> TokenStream { |
| 386 | let args: Punctuated = parse_macro_input!(attr with Punctuated<Meta, Token![,]>::parse_terminated); |
| 387 | let input: ItemImpl = parse_macro_input!(item as ItemImpl); |
| 388 | ifaceTokenStream::expand::<iface::old::ImplAttributes, iface::old::MethodAttributes>(args, input) |
| 389 | .unwrap_or_else(|err: Error| err.to_compile_error()) |
| 390 | .into() |
| 391 | } |
| 392 | |
| 393 | /// Derive macro for implementing [`zbus::DBusError`] trait. |
| 394 | /// |
| 395 | /// This macro makes it easy to implement the [`zbus::DBusError`] trait for your custom error type |
| 396 | /// (currently only enums are supported). |
| 397 | /// |
| 398 | /// If a special variant marked with the `zbus` attribute is present, `From<zbus::Error>` is |
| 399 | /// also implemented for your type. This variant can only have a single unnamed field of type |
| 400 | /// [`zbus::Error`]. This implementation makes it possible for you to declare proxy methods to |
| 401 | /// directly return this type, rather than [`zbus::Error`]. |
| 402 | /// |
| 403 | /// Each variant (except for the special `zbus` one) can optionally have a (named or unnamed) |
| 404 | /// `String` field (which is used as the human-readable error description). |
| 405 | /// |
| 406 | /// # Example |
| 407 | /// |
| 408 | /// ``` |
| 409 | /// use zbus_macros::DBusError; |
| 410 | /// |
| 411 | /// #[derive(DBusError, Debug)] |
| 412 | /// #[zbus(prefix = "org.myservice.App" )] |
| 413 | /// enum Error { |
| 414 | /// #[zbus(error)] |
| 415 | /// ZBus(zbus::Error), |
| 416 | /// FileNotFound(String), |
| 417 | /// OutOfMemory, |
| 418 | /// } |
| 419 | /// ``` |
| 420 | /// |
| 421 | /// [`zbus::DBusError`]: https://docs.rs/zbus/latest/zbus/trait.DBusError.html |
| 422 | /// [`zbus::Error`]: https://docs.rs/zbus/latest/zbus/enum.Error.html |
| 423 | /// [`zvariant::Type`]: https://docs.rs/zvariant/latest/zvariant/trait.Type.html |
| 424 | /// [`serde::Serialize`]: https://docs.rs/serde/1.0.132/serde/trait.Serialize.html |
| 425 | #[proc_macro_derive (DBusError, attributes(zbus))] |
| 426 | pub fn derive_dbus_error(input: TokenStream) -> TokenStream { |
| 427 | let input: DeriveInput = parse_macro_input!(input as DeriveInput); |
| 428 | errorTokenStream::expand_derive(input) |
| 429 | .unwrap_or_else(|err: Error| err.to_compile_error()) |
| 430 | .into() |
| 431 | } |
| 432 | |