1 //! Macros managing requests and responses. 2 //! 3 //! Our protocol uses the Result(T) type to communicate rich errors to 4 //! the client. These macros deal with sending a request using the 5 //! asynchronous I/O framework Tokio, and decoding the result. 6 //! 7 //! This implementation uses macros instead of functions to interface 8 //! with the code stubs generated by the RPC compiler. 9 10 // Sends request and decodes result. 11 // 12 // Sends the given request and decodes the result. 13 macro_rules! make_request { 14 ( $core: expr, $request: expr ) => {{ 15 use crate::node::result::Which; 16 17 let r: std::result::Result<Result<_>, capnp::Error> = $core.run( 18 $request.send().promise 19 .and_then(|response| -> Promise<Result<_>, capnp::Error> { 20 let r = pry!(pry!(pry!(response.get()).get_result()).which()); 21 let r = match r { 22 /* The Result. */ 23 Which::Ok(Ok(x)) => Ok(x), 24 Which::Err(Ok(e)) => Err(anyhow::Error::from(e)), 25 /* Protocol violations. */ 26 Which::Ok(Err(e)) => Err(anyhow::Error::from(e)), 27 Which::Err(Err(e)) => Err(anyhow::Error::from(e)), 28 }; 29 Promise::ok(r) 30 })); 31 r? 32 }} 33 } 34 35 macro_rules! make_request_map { 36 ( $core: expr, $request: expr, $map: expr ) => {{ 37 use crate::node::result::Which; 38 39 let r: std::result::Result<Result<_>, capnp::Error> = $core.run( 40 $request.send().promise 41 .and_then(|response| -> Promise<Result<_>, capnp::Error> { 42 let r = pry!(pry!(pry!(response.get()).get_result()).which()); 43 let r = match r { 44 /* The Result. */ 45 Which::Ok(Ok(x)) => $map(x), 46 Which::Err(Ok(e)) => Err(anyhow::Error::from(e)), 47 /* Protocol violations. */ 48 Which::Ok(Err(e)) => Err(anyhow::Error::from(e)), 49 Which::Err(Err(e)) => Err(anyhow::Error::from(e)), 50 }; 51 Promise::ok(r) 52 })); 53 r? 54 }} 55 } 56 57 /// These macros are for server functions. Because they use the 58 /// 'results' parameter, they must be bound explicitly at the 59 /// beginning of the function. 60 macro_rules! bind_results { 61 ( $results: ident ) => { 62 #[allow(unused)] 63 const DEBUG_BACKEND_ERRORS: bool = false; 64 65 /// Behaves like `return Err(_)` for server functions. 66 #[allow(unused_macros)] 67 macro_rules! fail { 68 ( $expr:expr ) => {{ 69 if DEBUG_BACKEND_ERRORS { 70 eprintln!("{}:{}: {:?}", file!(), line!(), $expr); 71 } 72 pry!($results.get().get_result()).set_err($expr); 73 return Promise::ok(()); 74 }}; 75 } 76 77 /// Behaves like `try!` for server functions. 78 /// 79 /// If the given expression evaluates to Err(_), the error is 80 /// stored in the result and the function terminates. 81 #[allow(unused_macros)] 82 macro_rules! sry { 83 ( $expr:expr ) => {{ 84 match $expr { 85 Ok(x) => x, 86 Err(x) => { 87 if DEBUG_BACKEND_ERRORS { 88 eprintln!("{}:{}: {:?}", file!(), line!(), x); 89 } 90 pry!($results.get().get_result()).set_err(x.into()); 91 return Promise::ok(()); 92 }, 93 } 94 }}; 95 } 96 }; 97 } 98