qrpc_sdk/
lib.rs

1//! A toolkit for writing clients on the qrpc message bus.  This bus
2//! is the backbone of the [qaul.net](https://qaul.net) service
3//! ecosystem.  With it you can create applications (called
4//! "services") that interact with a `libqaul` instance, and other
5//! services on the same message broker.
6//!
7//! These crate docs describe the API and basic usage.  For an
8//! overview of the core concepts of this ecosystem, consult the
9//! [contributors manual][manual].
10//!
11//! Additionally, you can access documentation of the internal
12//! utilities by passing "`--features internals`" to your cargo
13//! invocation.  These components are exposed via the API either way,
14//! but only documented on demand to not clutter the main
15//! documentation.
16//!
17//!
18//! [manual]: https://docs.qaul.org/contributors/technical/rpc-layer
19//!
20//! ## Using this sdk
21//!
22//! In order to interact with a running [`qrpc-broker`] instance your
23//! service needs to register itself and it's capabilities.
24//!
25//! First your service needs a place to save some state, composing
26//! different parts of this sdk together to create an app.
27//!
28//! You create a [`Service`] and [`RpcSocket`] and connect to the
29//! rpc-broker socket.  The first thing you do with this connection is
30//! call `register(...)` on the `Service`.  This establishes the
31//! connection, the broker saves your service in it's address lookup
32//! table, and you get assigned a hash-id to identify you in future
33//! interactions.
34//!
35//! [`qrpc-broker`]: ../qrpc_broker/index.html
36//! [`Service`]: ./struct.Service.html
37//! [`RpcSocket`]: ./struct.RpcSocket.html
38//!
39//! ```
40//! # async fn foo() -> Result<(), qrpc_sdk::error::RpcError> {
41//! use qrpc_sdk::{Service, RpcSocket, default_socket_path};
42//!
43//! let mut serv = Service::new("com.example.myapp", 1, "A simple app");
44//! let (addr, port) = default_socket_path();
45//! let sock = RpcSocket::connect(addr, port).await?;
46//!
47//! serv.register(sock).await?;
48//! println!("Service registered! ID: {}", serv.hash_id().unwrap());
49//! # Ok(())
50//! # }
51//! ```
52//!
53//! Next you need to include the client-lib of the component you want
54//! to use, and call `connect(...)` on your service with the component
55//! initialiser.
56//!
57//! ```
58//! # async fn foo() -> Result<(), qrpc_sdk::error::RpcError> {
59//! # use qrpc_sdk::{Service, RpcSocket, default_socket_path};
60//! # let mut serv = Service::new("com.example.myapp", 1, "A simple app");
61//! # let (addr, port) = default_socket_path();
62//! # let sock = RpcSocket::connect(addr, port).await?;
63//! # serv.register(sock).await?;
64//!
65//! // serv.connect(libqaul_rpc::Init).await?;
66//! # Ok(())
67//! # }
68//! ```
69//!
70//! This will establish a connection with the `libqaul` component and
71//! verifies it's capability set.  This mechanism is provided by the
72//! [`ServiceConnector`].  Your service will also have to implement
73//! this mechanism to be usable by other services on the qrpc bus.
74//!
75//! [`ServiceConnector`]: ./trait.ServiceConnector.html
76//!
77//! After that you can call functions on the public API type of the
78//! component.  You can get a copy of it via your service handle.
79//!
80//! ```
81//! # async fn foo() -> Result<(), qrpc_sdk::error::RpcError> {
82//! # use qrpc_sdk::{Service, RpcSocket, default_socket_path};
83//! # let mut serv = Service::new("com.example.myapp", 1, "A simple app");
84//! # let (addr, port) = default_socket_path();
85//! # let sock = RpcSocket::connect(addr, port).await?;
86//! # serv.register(sock).await?;
87//!
88//! // net.qaul.libqaul is exposed as libqaul_rpc.COMP_ID
89//! // let users = serv.component("net.qaul.libqaul").list_users().await?;
90//! // println!("Available users: {:?}", users);
91//! # Ok(())
92//! # }
93//! ```
94//!
95//! If you want to see a minimal example of the smallest functional
96//! service, see the [`ping`] crate.
97//!
98//! [`ping`]: https://git.open-communication.net/qaul/qaul.net/-/tree/develop/services%2Fping/
99
100#[macro_use]
101extern crate tracing;
102
103// FIXME: currently the protocols have to be in the root of the crate
104// because of [this issue][i] in the capnproto codegen units:
105// [i]: https://github.com/capnproto/capnproto-rust/issues/194
106pub(crate) mod base_capnp {
107    #![allow(unused)] // don't bother me pls
108    include!(concat!(env!("OUT_DIR"), "/schema/base_capnp.rs"));
109}
110pub(crate) mod types_capnp {
111    #![allow(unused)] // don't bother me pls
112    include!(concat!(env!("OUT_DIR"), "/schema/types_capnp.rs"));
113}
114pub(crate) mod cap_capnp {
115    #![allow(unused)] // don't bother me pls
116    include!(concat!(env!("OUT_DIR"), "/schema/cap_capnp.rs"));
117}
118
119/// qrpc message types
120///
121/// This interface is exposed to let other parts of the qrpc ecosystem
122/// parse and generate these types.  When using this library directly,
123/// try to avoid using them.  Use the main type interface documented
124/// in the root of the crate instead.
125#[cfg_attr(not(feature = "internals"), doc(hidden))]
126pub mod types {
127    pub use crate::base_capnp::rpc_message;
128    pub use crate::types_capnp::service;
129}
130
131/// qrpc message types
132///
133/// As with the data types used by this crate, try to avoid using them
134/// directly.  Instead use the main API of the crate which invoces
135/// these types internally
136#[cfg_attr(not(feature = "internals"), doc(hidden))]
137pub mod rpc {
138    pub use crate::cap_capnp::{capabilities, register, sdk_reply, unregister, upgrade};
139}
140
141mod service;
142mod socket;
143
144pub mod builders;
145pub mod error;
146pub mod io;
147pub mod parser;
148
149pub use identity::Identity;
150pub use service::{Service, ServiceConnector};
151pub use socket::{default_socket_path, RpcSocket};
152
153/// The address of the qrpc broker itself
154pub const BROKER_ADDRESS: &'static str = "org.qaul._broker";