tonic-rpc is a macro that generates the traits and stubs used by tonic from Rust definitions instead of proto files.

This means that you can get all the benefits of tonic while using regular Rust types and without needing to use proto files or build scripts. Of course, this comes at the sacrifice of interoperability.

Crates.io Documentation Build Status License Downloads

Alternatives

tarpc is an excellent RPC library that also defines services as a Rust trait.

Required dependencies

toml tonic = "0.8" tonic-rpc = { version = "0.2", features = [ <enabled-codecs> ] }

Example

Instead of defining a proto file, define a service as a trait: ```rust

[tonicrpc::tonicrpc(json)]

trait Increment { fn increment(arg: i32) -> i32; } `` The attribute **#[tonic_rpc(json)]** indicates that this service will serialize the requests and responses usingjson. Other [encodings are available](#encodings). The arguments and return values for each function must implement serde::Serializeandserde::Deserialize`.

The service can be implemented by defining an impl: ```rust struct State;

[tonic::async_trait]

impl incrementserver::Increment for State { async fn increment( &self, request: tonic::Request, ) -> Result, tonic::Status> { Ok(tonic::Response::new(request.intoinner() + 1)) } } ```

And a server and client can be run: rust async fn run_client_server() { let mut listener = tokio::net::TcpListener::bind("[::1]:0").await.unwrap(); let addr = listener.local_addr().unwrap(); tokio::spawn(async move { tonic::transport::Server::builder() .add_service(increment_server::IncrementServer::new(State)) .serve_with_incoming(tokio_stream::wrappers::TcpListenerStream::new(listener)) .await }); let mut client = increment_client::IncrementClient::connect(format!("http://{}", addr)) .await .unwrap(); let response = client.increment(32).await.unwrap().into_inner(); assert_eq!(33, response); }

The full example is available here. Further examples are available in the tests folder.

Encodings

Multiple codecs are available for serializing the RPC request/response types. Each codec is enabled by a feature flag. At least one of these features must be enabled. - bincode - using bincode - cbor - using serde_cbor - json - using serde_json - messagepack - using rmp-serde

E.g. To use the encode using cbor, use the attribute ```rust

[tonicrpc::tonicrpc(cbor)]

and include toml tonic-rpc = { version = "0.2", features = [ "cbor" ]} `` inCargo.toml`.

Streaming

Streaming can be added on the client or server side by adding the attributes #[client_streaming] or #[server_streaming] to a function in the service trait. These behave the same as if the stream keyword were added to a proto definition.

Examples that use streaming can be found in the tests folder.

Request/Response types

The traits and functions generated by tonic-rpc will be transformations of the methods defined in the tonic_rpc trait that have been modified to add handling of gRPC request/response types, async, and streaming.

This is a summary of how signatures are transformed:

Arguments

rust fn f(x: X, y:Y) -> .. becomes rust async fn f(&self, arg: tonic::Request<(X,Y)>) -> ..

Return value

rust fn f(..) -> Z becomes rust async fn f(..) -> Result<tonic::Response<Z>, tonic::Status>

Streaming arguments

```rust

[client_streaming]

fn f(x:X) -> .. becomes rust async fn f(&self, arg: tonic::Request>) -> .. ```

Streaming return value

```rust

[server_streaming]

fn f(..) -> Z becomes rust type FStream: Stream>;

async fn f(..) -> Result::, tonic::Status> ```