# capnp-rpc-rust [![crates.io](https://img.shields.io/crates/v/capnp-rpc.svg)](https://crates.io/crates/capnp-rpc) [documentation](https://docs.rs/capnp-rpc/) This is a [level one](https://capnproto.org/rpc.html#protocol-features) implementation of the Cap'n Proto remote procedure call protocol. It is a fairly direct translation of the original [C++ implementation](https://github.com/sandstorm-io/capnproto). ## Defining an interface First, make sure that the [`capnp` executable](https://capnproto.org/capnp-tool.html) is installed on your system, and that you have the [`capnpc`](https://crates.io/crates/capnpc) crate in the `build-dependencies` section of your `Cargo.toml`. Then, in a file named `foo.capnp`, define your interface: ```capnp @0xa7ed6c5c8a98ca40; interface Bar { baz @0 (x :Int32) -> (y :Int32); } interface Qux { quux @0 (bar :Bar) -> (y :Int32); } ``` Now you can invoke the schema compiler in a [`build.rs`](http://doc.crates.io/build-script.html) file, like this: ```rust fn main() { ::capnpc::CompilerCommand::new().file("foo.capnp").run().unwrap(); } ``` and you can include the generated code in your project like this: ```rust pub mod foo_capnp { include!(concat!(env!("OUT_DIR"), "/foo_capnp.rs")); } ``` ## Calling methods on an RPC object For each defined interface, the generated code includes a `Client` struct that can be used to call the interface's methods. For example, the following code calls the `Bar.baz()` method: ```rust fn call_bar(client: ::foo_capnp::bar::Client) -> Box> { let mut req = client.baz_request(); req.get().set_x(11); Box::new(req.send().promise.and_then(|response| { Ok(response.get()?.get_y()) })) } ``` A `bar::Client` is a reference to a possibly-remote `Bar` object. The Cap'n Proto RPC runtime tracks the number of such references that are live at any given time and automatically drops the object when none are left. ## Implementing an interface The generated code also includes a `Server` trait for each of your interfaces. To create an RPC-enabled object, you must implement that trait. ```rust struct MyBar {} impl ::foo_capnp::bar::Server for MyBar { fn baz(&mut self, params: ::foo_capnp::bar::BazParams, mut results: ::foo_capnp::bar::BazResults) -> Promise<(), ::capnp::Error> { // `pry!` is defined in capnp_rpc. It's analogous to `try!`. results.get().set_y(pry!(params.get()).get_x() + 1); Promise::ok(()) } } ``` Then you can convert your object into a capability client like this: ```rust let client: foo_capnp::bar::Client = capnp_rpc::new_client(MyBar {}); ``` This new `client` can now be sent across the network. You can use it as the bootstrap capability when you construct an `RpcSystem`, and you can pass it in RPC method arguments and results. ## Async methods The methods of the generated `Server` traits return a value of type `Promise<(), ::capnp::Error>`. A `Promise` is either an immediate value, constructed by `Promise::ok()` or `Promise::err()`, or it is a wrapper of a `Future`, constructed by `Promise::from_future()`. The results will be sent back to the method's caller once two things have happened: 1. The `Results` struct has been dropped. 2. The returned `Promise` has resolved. Usually (1) happens before (2). Here's an example of a method implementation that does not return immediately: ```rust struct MyQux {} impl ::foo_capnp::qux::Server for MyQux { fn quux(&mut self, params: ::foo_capnp::qux::QuuxParams, mut results: ::foo_capnp::wux::QuuxResults) -> Promise<(), ::capnp::Error> { // Call `baz()` on the passed-in client. let bar_client = pry!(pry!(params.get()).get_bar()); let mut req = bar_client.baz_request(); req.get().set_x(42); Promise::from_future(req.send().promise.and_then(move |response| { results.get().set_y(response.get()?.get_y()); Ok(()) })) } } ``` It's possible for multiple calls of `quux()` to be active at the same time on the same object, and they do not need to return in the same order as they were called. ## Further reading * The [hello world example](/capnp-rpc/examples/hello-world) demonstrates a basic request/reply pattern. * The [calculator example](/capnp-rpc/examples/calculator) demonstrates how to use [promise pipelining](https://capnproto.org/rpc.html#time-travel-promise-pipelining). * The [pubsub example](/capnp-rpc/examples/pubsub) shows how even an interface with no methods can be useful. * The [Sandstorm raw API example app](https://github.com/dwrensha/sandstorm-rawapi-example-rust) shows how Sandstorm lets you write web apps using Cap'n Proto instead of HTTP.