DBus async library

Hey Rustaceans,
I create a pure Rust(no C code) written async DBus library. It uses tokio library for the async part. I would appreciate your feedback.

These libraries are not finished yet.

Here an example of a method call (here are more examples):

use dbus_async::DBus;
use dbus_message_parser::Message;

#[tokio::main]
async fn main() {
    let (dbus, _server_handle) = DBus::session(true)
        .await
        .expect("failed to get the DBus object");

    // Create a MethodCall.
    let msg = Message::method_call(
        "org.freedesktop.DBus",
        "/org/freedesktop/DBus",
        "org.freedesktop.DBus.Peer",
        "Ping",
    );

    // Send the message and get the return message.
    let return_msg = dbus.call(msg).await;

    // Print the return message.
    println!("{:?}", return_msg);
}

And if you want to write a DBus service then you can use the dbus-async-derive proc macro (here are more examples):

use dbus_async::{Binder, DBus};
use dbus_async_derive::Handler;
use dbus_message_parser::MessageHeader;

#[derive(Handler)]
#[interface(
    "org.example.interface",
    method("ExampleMethod", method),
    property("ExampleProperty", "s", get_property = "get", set_property = "set")
)]
struct DBusObject {
    property: String,
}

impl DBusObject {
    async fn method(
        &mut self,
        dbus: &DBus,
        _msg_header: &MessageHeader,
    ) -> Result<(), (String, String)> {
        // The code of the method
        println!(
            "The DBus socket where the message came from: {}",
            dbus.get_socket_path()
        );
        // ...
        Ok(())
    }

    async fn get_property(
        &mut self,
        _dbus: &DBus,
        _msg_header: &MessageHeader,
    ) -> Result<String, (String, String)> {
        Ok(self.property.clone())
    }

    async fn set_property(
        &mut self,
        _dbus: &DBus,
        _msg_header: &MessageHeader,
        new_value: String,
    ) -> Result<(), (String, String)> {
        self.property = new_value;
        Ok(())
    }
}

#[tokio::main]
async fn main() {
    let (dbus, _connection_join_handle) = DBus::session(true)
        .await
        .expect("failed to get the DBus object");
    // Create the object
    let dbus_object = DBusObject {
        property: "".to_string(),
    };
    let object_path = "/org/example/object/path";
    dbus_object
        .bind(dbus, object_path)
        .await
        .expect("Something went wrong");
}

(There is the same post on reddit)

3 Likes