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

#[macro_use]
extern crate tracing;

// FIXME: currently the protocols have to be in the root of the crate
// because of [this issue][i] in the capnproto codegen units:
// [i]: https://github.com/capnproto/capnproto-rust/issues/194
pub(crate) mod base_capnp {
    #![allow(unused)] // don't bother me pls
    include!(concat!(env!("OUT_DIR"), "/schema/base_capnp.rs"));
}
pub(crate) mod types_capnp {
    #![allow(unused)] // don't bother me pls
    include!(concat!(env!("OUT_DIR"), "/schema/types_capnp.rs"));
}
pub(crate) mod cap_capnp {
    #![allow(unused)] // don't bother me pls
    include!(concat!(env!("OUT_DIR"), "/schema/cap_capnp.rs"));
}

/// qrpc message types
///
/// This interface is exposed to let other parts of the qrpc ecosystem
/// parse and generate these types.  When using this library directly,
/// try to avoid using them.  Use the main type interface documented
/// in the root of the crate instead.
#[cfg_attr(not(feature = "internals"), doc(hidden))]
pub mod types {
    pub use crate::base_capnp::rpc_message;
    pub use crate::types_capnp::service;
}

/// qrpc message types
///
/// As with the data types used by this crate, try to avoid using them
/// directly.  Instead use the main API of the crate which invoces
/// these types internally
#[cfg_attr(not(feature = "internals"), doc(hidden))]
pub mod rpc {
    pub use crate::cap_capnp::{capabilities, register, sdk_reply, unregister, upgrade};
}

mod service;
mod socket;

pub mod builders;
pub mod error;
pub mod io;
pub mod parser;

pub use identity::Identity;
pub use service::{Service, ServiceConnector};
pub use socket::{default_socket_path, RpcSocket};

/// The address of the qrpc broker itself
pub const BROKER_ADDRESS: &'static str = "org.qaul._broker";