#dbus #ipc #zbus #type-safety

zbus-lockstep

Keep types in lockstep with DBus XML definitions

13 releases

new 0.5.0 Dec 2, 2024
0.4.4 Mar 18, 2024
0.4.0 Feb 19, 2024
0.3.1 Oct 2, 2023
0.1.0 Aug 8, 2023

#400 in Cryptography

Download history 59/week @ 2024-08-12 23/week @ 2024-08-19 73/week @ 2024-08-26 31/week @ 2024-09-02 21/week @ 2024-09-09 30/week @ 2024-09-16 35/week @ 2024-09-23 32/week @ 2024-09-30 6397/week @ 2024-10-07 10444/week @ 2024-10-14 11912/week @ 2024-10-21 14833/week @ 2024-10-28 23467/week @ 2024-11-04 19263/week @ 2024-11-11 21235/week @ 2024-11-18 22268/week @ 2024-11-25

87,635 downloads per month
Used in 52 crates (2 directly)

MIT license

52KB
775 lines

zbus-lockstep

CI Maintenance crates-io api-docs

zbus-lockstep helps keep type definitions in lockstep with DBus XML descriptions, using zbus-xml.

It offers means to match your type's signature - <T as zvariant::Type>::signature() - with a corresponding signature retrieved from a DBus XML file.

This way zbus-lockstep prevents definitions from drifting apart.

Motivation

In the context of IPC over DBus - especially when there are multiple implementations of servers and/or clients - it is necessary for each implementation to send what others expect and that expectations are in accordance with what is sent over the bus.

The XML protocol-descriptions may act as a shared frame of reference or "single source of all truth" for all implementers. Having a single point of reference helps all implementers meet expectations on protocol conformance.

Keeping the types you send over DBus in lockstep with currently valid protocol-descriptions will reduce chances of miscommunication or failure to communicate.

Usage

Add zbus-lockstep to Cargo.toml's dev-dependencies:

[dev-dependencies]
zbus-lockstep = "0.5.0"

Consider the followwing XML description, an interface with a single signal.

<node>
  <interface name="org.example.Node">

    <signal name="RemoveNode">
      <arg name="nodeRemoved" type="(so)"/>
    </signal>

  </interface>
</node>

The type in our implementation might look like this:

#[derive(Type)]
struct Node {
    name: String,
    path: OwnedObjectPath,
}

The derive macro in this example implements the zvariant::Type. This means we can now call <Node as Type::signature(), which will return a zvariant::Signature of the type.

The test below shows how zbus-lockstep may be used given what we know about the type.

    use zbus_lockstep;

    #[test]
    fn test_get_signal_body_type_remove_node() {
        let xml = PathBuf::from("../xml/test_definition_file.xml");
        let iface = "org.example.Node";
        let member = "RemoveNode";

        let signature = get_signal_body_type(xml, iface, member, None).unwrap();
        assert_eq!(signature, Signature::from_str_unchecked("(so)"));
    }

Alongside the functions, macros are provided which - if the path to the definitions is known - can retrieve signatures more succinctly.

#[test]
fn macro_retrieve_signal_body_remove_node() {
std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
use zbus_lockstep;

let sig = signal_body_type_signature!("RemoveNode");
assert_eq!(sig, zvariant::Signature::from_str_unchecked("(so)"));       
}

Note

When using XML descriptions as point of reference, you should ensure that the descriptions in use are always the most recent available.

Automated synchronizing would be preferred.

Acknowledgement

This crate started out as a fork of Tait Hoyem's zbus-xml-match.

LICENSE

MIT

Dependencies

~5MB
~96K SLoC