Files
tarpc/tarpc/examples
Tim Kuehn fb5022b1c0 cargo fmt
2019-07-29 22:08:53 -07:00
..
2019-07-29 22:08:53 -07:00
2019-07-29 22:04:04 -07:00

// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

#![feature(async_await)]

use futures::{
    future::{self, Ready},
    prelude::*,
};
use rpc::{
    client, context,
    server::{BaseChannel, Channel},
};
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]
pub trait Service {
    async fn 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<String>;

    fn hello(self, _: context::Context, name: String) -> Self::HelloFut {
        future::ready(format!("Hello, {}!", name))
    }
}

#[runtime::main(runtime_tokio::Tokio)]
async fn main() -> io::Result<()> {
    // bincode_transport is provided by the associated crate bincode-transport. It makes it easy
    // to start up a serde-powered bincode serialization strategy over TCP.
    let mut transport = bincode_transport::listen(&"0.0.0.0:0".parse().unwrap())?;
    let addr = transport.local_addr();

    let server = async move {
        // For this example, we're just going to wait for one connection.
        let client = transport.next().await.unwrap().unwrap();

        // `Channel` is a trait representing a server-side connection. It is a trait to allow
        // for some channels to be instrumented: for example, to track the number of open connections.
        // BaseChannel is the most basic channel, simply wrapping a transport with no added
        // functionality.
        BaseChannel::with_defaults(client)
            // serve is generated by the tarpc::service! macro. It takes as input any type implementing
            // the generated Service trait.
            .respond_with(serve(HelloServer))
            .await;
    };
    let _ = runtime::spawn(server);

    let transport = bincode_transport::connect(&addr).await?;

    // new_stub is generated by the tarpc::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(), transport).await?;

    // The client has an RPC method for each RPC defined in tarpc::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?;

    eprintln!("{}", hello);

    Ok(())
}