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
|
//! Macros managing requests and responses.
//!
//! Our protocol uses the Result(T) type to communicate rich errors to
//! the client. These macros deal with sending a request using the
//! asynchronous I/O framework Tokio, and decoding the result.
//!
//! This implementation uses macros instead of functions to interface
//! with the code stubs generated by the RPC compiler.
// Sends request and decodes result.
//
// Sends the given request and decodes the result.
macro_rules! make_request {
( $core: expr, $request: expr ) => {{
use crate::node::result::Which;
let r: std::result::Result<Result<_>, capnp::Error> = $core.run(
$request.send().promise
.and_then(|response| -> Promise<Result<_>, capnp::Error> {
let r = pry!(pry!(pry!(response.get()).get_result()).which());
let r = match r {
/* The Result. */
Which::Ok(Ok(x)) => Ok(x),
Which::Err(Ok(e)) => Err(anyhow::Error::from(e)),
/* Protocol violations. */
Which::Ok(Err(e)) => Err(anyhow::Error::from(e)),
Which::Err(Err(e)) => Err(anyhow::Error::from(e)),
};
Promise::ok(r)
}));
r?
}}
}
macro_rules! make_request_map {
( $core: expr, $request: expr, $map: expr ) => {{
use crate::node::result::Which;
let r: std::result::Result<Result<_>, capnp::Error> = $core.run(
$request.send().promise
.and_then(|response| -> Promise<Result<_>, capnp::Error> {
let r = pry!(pry!(pry!(response.get()).get_result()).which());
let r = match r {
/* The Result. */
Which::Ok(Ok(x)) => $map(x),
Which::Err(Ok(e)) => Err(anyhow::Error::from(e)),
/* Protocol violations. */
Which::Ok(Err(e)) => Err(anyhow::Error::from(e)),
Which::Err(Err(e)) => Err(anyhow::Error::from(e)),
};
Promise::ok(r)
}));
r?
}}
}
/// These macros are for server functions. Because they use the
/// 'results' parameter, they must be bound explicitly at the
/// beginning of the function.
macro_rules! bind_results {
( $results: ident ) => {
#[allow(unused)]
const DEBUG_BACKEND_ERRORS: bool = false;
/// Behaves like `return Err(_)` for server functions.
#[allow(unused_macros)]
macro_rules! fail {
( $expr:expr ) => {{
if DEBUG_BACKEND_ERRORS {
eprintln!("{}:{}: {:?}", file!(), line!(), $expr);
}
pry!($results.get().get_result()).set_err($expr);
return Promise::ok(());
}};
}
/// Behaves like `try!` for server functions.
///
/// If the given expression evaluates to Err(_), the error is
/// stored in the result and the function terminates.
#[allow(unused_macros)]
macro_rules! sry {
( $expr:expr ) => {{
match $expr {
Ok(x) => x,
Err(x) => {
if DEBUG_BACKEND_ERRORS {
eprintln!("{}:{}: {:?}", file!(), line!(), x);
}
pry!($results.get().get_result()).set_err(x.into());
return Promise::ok(());
},
}
}};
}
};
}
|