rustbus/
lib.rs

1//! # Rustbus
2//! Rustbus is a dbus library that allows for clients to perform method_calls on services on the bus or to implement your own service that listens on the bus.
3//!
4//! ## Quickstart
5//! ```rust,no_run
6//! use rustbus::{
7//!     connection::Timeout,
8//!     get_session_bus_path,
9//!     DuplexConn,
10//!     RpcConn,
11//!     MessageBuilder,
12//!     connection::ll_conn::force_finish_on_error
13//! };
14//! fn main() -> Result<(), rustbus::connection::Error> {
15//!     // To get a connection going you need to connect to a bus.
16//!     // You will likely use either the session or the system bus.
17//!     let session_path = get_session_bus_path()?;
18//!     let mut con = DuplexConn::connect_to_bus(session_path, true)?;
19//!     // Dont forget to send the obligatory hello message.
20//!     // send_hello wraps the call and parses the response for convenience.
21//!     let unique_name = con.send_hello(Timeout::Infinite)?;
22//!
23//!     // Or use the more higher level abstraction of a RpcConn.
24//!     // This builds the connection and sends the hello for you
25//!     let mut rpc_con = RpcConn::session_conn(Timeout::Infinite).unwrap();
26//!
27//!     // Next you will probably want to create a new message to send out to the world
28//!     let mut sig = MessageBuilder::new()
29//!         .signal(
30//!             "io.killing.spark",
31//!             "TestSignal",
32//!             "/io/killing/spark",
33//!         )
34//!         .build();
35//!     
36//!     // To put parameters into that message you use the sig.body.push_param functions.
37//!     // These accept anything that can be marshalled into a dbus parameter
38//!     // You can derive or manually implement that trait for your own types if you need that.
39//!     sig.body.push_param("My cool new Signal!").unwrap();
40//!     
41//!     // Now send you signal to all that want to hear it!
42//!     con.send.send_message(&sig)?.write_all().map_err(force_finish_on_error)?;
43//!     
44//!     // To receive messages sent to you you can call the various functions on the RecvConn.
45//!     // The simplest is this:
46//!     let message = con.recv.get_next_message(Timeout::Infinite)?;  
47//!     
48//!     // Now you can inspect the message.dynheader for all the metadata on the message
49//!     println!("The messages dynamic header: {:?}", message.dynheader);
50//!
51//!     // After inspecting that dynheader you should know which content the message should contain
52//!     let cool_string = message.body.parser().get::<&str>().unwrap();
53//!     println!("Received a cool string: {}", cool_string);
54//!     Ok(())
55//! }
56//! ```
57//!
58//! ## Other connection Types
59//! There are some more connection types in the connection module. These are convenience wrappes around the concepts presented in the quickstart.
60//! * RpcConn is meant for clients calling methods on services on the bus
61//! * DispatchConn is meant for services that need to dispatch calls to many handlers.
62//!
63//! Since different usecases have different constraints you might need to write your own wrapper around the low level conn. This should not be too hard
64//! if you copy the existing ones and modify them to your needs. If you have an issue that would be helpful for others I would of course consider adding
65//! it to this libary.
66//!
67//! ## Params and Marshal and Unmarshal
68//! This lib started out as an attempt to understand how dbus worked. Thus I modeled the types a closely as possible with enums, which is still in the params module.
69//! This is kept around for weird weird edge-cases where that might be necessary but they should not generally be used.
70//!
71//! Instead you should be using the Marshal and Unmarshal traits which are implemented for most common types you will need. The idea is to map rust types
72//! as closely as possible to dbus types. The trivial types like String and u64 etc are dealt with easily. For tuple-structs there are impls up to a
73//! certain size. After that you'd need to copy the impl from this lib and extend it accordingly. This might be dealt with in the future if variadic generics get
74//! added to rust.
75//!
76//! For structs there is a derive proc-macro that derives the necessary trait impls for you. Look into rustbus_derive if this is of need for you.
77//!
78//! For Variants there is a macro dbus_variant_sig! and dbus_variant_var! which will generate an enum and the Marshal and Unmarshal impls for you. These might get
79//! replaced with a proc-macro derive like it exists already for structs.
80//!
81//! The doc for the traits gives more specifics on how to implement them for your own types if necessary.
82//!
83//! There is an exmaple for all of this in `examples/user_defined_types.rs`.
84//! And for the deriving for structs there is an example in `examples/deriving.rs`
85//!
86//! ## Filedescriptors
87//! Dbus can send filedescriptors around for you. Rustbus supports this. There is a special wrapper type in the wire module. This type tries to sensibly deal with
88//! the pitfalls of sending and receiving filedescriptors in a sensible way. If you see any issues with the API or have wishes for extensions to the API please
89//! open an issue.
90//!
91//! ## Byteorders
92//! Dbus supports both big and little endian and so does rustbus. You can specify how a message should be marshalled when you create the MessageBuilder. Messages
93//! can be received in any byteorder and will be transparently unmarshalled into the byteorder you CPU uses. Note that unmarshalling from/to the native byteorder will
94//! be faster. The default byteorder is little endian.
95
96pub mod auth;
97pub mod connection;
98pub mod message_builder;
99pub mod params;
100pub mod peer;
101pub mod signature;
102pub mod standard_messages;
103pub mod wire;
104
105// reexport derive macros
106pub use rustbus_derive::*;
107
108// TODO create a rustbus::prelude
109
110// needed to make own filters in RpcConn
111pub use message_builder::MessageType;
112
113// needed to create a connection
114pub use connection::dispatch_conn::DispatchConn;
115pub use connection::ll_conn::DuplexConn;
116pub use connection::ll_conn::RecvConn;
117pub use connection::ll_conn::SendConn;
118pub use connection::rpc_conn::RpcConn;
119pub use connection::{get_session_bus_path, get_system_bus_path};
120
121// needed to make new messages
122pub use message_builder::{CallBuilder, MessageBuilder, SignalBuilder};
123pub use wire::marshal::traits::Marshal;
124pub use wire::marshal::traits::Signature;
125pub use wire::unmarshal::traits::Unmarshal;
126
127#[cfg(test)]
128mod tests;
129
130/// The supported byte orders
131#[derive(Clone, Copy, Debug, PartialEq, Eq)]
132pub enum ByteOrder {
133    LittleEndian,
134    BigEndian,
135}
136
137impl ByteOrder {
138    const NATIVE: Self = match cfg!(target_endian = "little") {
139        true => ByteOrder::LittleEndian,
140        false => ByteOrder::BigEndian,
141    };
142}