Quickstart - toy-rpc Book

# Quickstart

A simple quickstart with `tokio` runtime is shown below. More examples can be found in the Example chapter.

## Initialize new project

`cargo new --lib toy_rpc_quickstart`

## Add dependencies

    [dependencies]
    tokio = { version = "1", features = ["rt-multi-thread", "macros", "net"] }
    toy-rpc = { version = "0.7.5", features = ["tokio_runtime", "server", "client"] }

## Project structure

    ./src
    ├── /bin
    │   ├── server.rs
    │   ├── client.rs
    └── lib.rs

In the `Cargo.toml`, you may need to specify the binaries with

    [[bin]]
    name = "server"
    path = "src/bin/server.rs"

    [[bin]]
    name = "client"
    path = "src/bin/client.rs"

## Define RPC service

In `src/lib.rs`

    // src/lib.rs

    pub mod rpc {
        use toy_rpc::macros::export_impl;
        pub struct Echo { }

        #[export_impl]
        impl Echo {
            #[export_method]
            pub async fn echo_i32(&self, arg: i32) -> Result<i32, String> {
                Ok(arg)
            }
        }
    }

## RPC server

In `src/bin/server.rs`

    // src/bin/server.rs

    use tokio::{task, net::TcpListener};
    use std::sync::Arc;
    use toy_rpc::Server;

    use toy_rpc_quickstart::rpc::Echo;

    #[tokio::main]
    async fn main() {
        let addr = "127.0.0.1:23333";

        // Creates an instance of the `Echo` service
        let echo_service = Arc::new(
            Echo { }
        );

        let server = Server::builder()
            .register(echo_service) // register service
            .build();
        let listener = TcpListener::bind(addr).await.unwrap();

        // Run the server in a separate task
        let handle = task::spawn(async move {
            println!("Starting server at {}", &addr);
            server.accept(listener).await.unwrap();
        });
        handle.await.expect("Error running the RPC server");
    }

## RPC client

In `src/bin/client.rs`

    use toy_rpc::Client;

    // import everything including the client stub generated by the macro
    use toy_rpc_quickstart::rpc::*;

    #[tokio::main]
    async fn main() {
        let addr = "127.0.0.1:23333";
        let client = Client::dial(addr).await.unwrap();

        let result: i32 = client
            .echo() // calling service `Echo`
            .echo_i32(3i32) // calling RPC method `echo_i32`
            .await
            .unwrap();
        println!("{:?}", result);

        // The above call is equivalent to
        let result: i32 = client
            .call("Echo.echo_i32", 3i32)
            .await
            .unwrap();
        println!("{:?}", result);
    }