diff --git a/README.md b/README.md index 7f84be0..273e0d8 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ First, let's set up the dependencies and service definition. ```rust #![feature(arbitrary_self_types, async_await, proc_macro_hygiene)] +# extern crate futures; use futures::{ compat::Executor01CompatExt, @@ -85,6 +86,27 @@ This service definition generates a trait called `Service`. Next we need to implement it for our Server struct. ```rust +# #![feature(arbitrary_self_types, async_await, proc_macro_hygiene)] +# extern crate futures; +# +# use futures::{ +# compat::Executor01CompatExt, +# future::{self, Ready}, +# prelude::*, +# }; +# use tarpc::{ +# client, context, +# server::{self, Handler}, +# }; +# use std::io; +# +# // This is the service definition. It looks a lot like a trait definition. +# // It defines one RPC, hello, which takes one arg, name, and returns a String. +# tarpc::service! { +# /// Returns a greeting for name. +# rpc hello(name: String) -> String; +# } +# // This is the type that implements the generated Service trait. It is the business logic // and is used to start the server. #[derive(Clone)] @@ -110,6 +132,43 @@ tarpc also ships a that uses bincode over TCP. ```rust +# #![feature(arbitrary_self_types, async_await, proc_macro_hygiene)] +# extern crate futures; +# +# use futures::{ +# compat::Executor01CompatExt, +# future::{self, Ready}, +# prelude::*, +# }; +# use tarpc::{ +# client, context, +# server::{self, Handler}, +# }; +# use std::io; +# +# // This is the service definition. It looks a lot like a trait definition. +# // It defines one RPC, hello, which takes one arg, name, and returns a String. +# tarpc::service! { +# /// Returns a greeting for name. +# rpc hello(name: String) -> String; +# } +# +# // This is the type that implements the generated Service trait. It is the business logic +# // and is used to start the server. +# #[derive(Clone)] +# struct HelloServer; +# +# impl Service for HelloServer { +# // Each defined rpc generates two items in the trait, a fn that serves the RPC, and +# // an associated type representing the future output by the fn. +# +# type HelloFut = Ready; +# +# fn hello(self, _: context::Context, name: String) -> Self::HelloFut { +# future::ready(format!("Hello, {}!", name)) +# } +# } +# async fn run() -> io::Result<()> { let (client_transport, server_transport) = tarpc::transport::channel::unbounded(); @@ -144,6 +203,71 @@ call `tarpc::init()` to initialize the executor tarpc uses internally to run background tasks for the client and server. ```rust +# #![feature(arbitrary_self_types, async_await, proc_macro_hygiene)] +# extern crate futures; +# +# use futures::{ +# compat::Executor01CompatExt, +# future::{self, Ready}, +# prelude::*, +# }; +# use tarpc::{ +# client, context, +# server::{self, Handler}, +# }; +# use std::io; +# +# // This is the service definition. It looks a lot like a trait definition. +# // It defines one RPC, hello, which takes one arg, name, and returns a String. +# tarpc::service! { +# /// Returns a greeting for name. +# rpc hello(name: String) -> String; +# } +# +# // This is the type that implements the generated Service trait. It is the business logic +# // and is used to start the server. +# #[derive(Clone)] +# struct HelloServer; +# +# impl Service for HelloServer { +# // Each defined rpc generates two items in the trait, a fn that serves the RPC, and +# // an associated type representing the future output by the fn. +# +# type HelloFut = Ready; +# +# fn hello(self, _: context::Context, name: String) -> Self::HelloFut { +# future::ready(format!("Hello, {}!", name)) +# } +# } +# +# async fn run() -> io::Result<()> { +# let (client_transport, server_transport) = tarpc::transport::channel::unbounded(); +# +# let server = server::new(server::Config::default()) +# // incoming() takes a stream of transports such as would be returned by +# // TcpListener::incoming (but a stream instead of an iterator). +# .incoming(stream::once(future::ready(Ok(server_transport)))) +# // serve is generated by the service! macro. It takes as input any type implementing +# // the generated Service trait. +# .respond_with(serve(HelloServer)); +# +# tokio::spawn(server.unit_error().boxed().compat()); +# +# // new_stub is generated by the service! macro. Like Server, it takes a config and any +# // Transport as input, and returns a Client, also generated by the macro. +# // by the service mcro. +# let mut client = new_stub(client::Config::default(), client_transport).await?; +# +# // The client has an RPC method for each RPC defined in service!. It takes the same args +# // as defined, with the addition of a Context, which is always the first arg. The Context +# // specifies a deadline and trace information which can be helpful in debugging requests. +# let hello = client.hello(context::current(), "Stim".to_string()).await?; +# +# println!("{}", hello); +# +# Ok(()) +# } +# fn main() { tarpc::init(tokio::executor::DefaultExecutor::current().compat()); tokio::run(run()