// 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. use futures::prelude::*; use tarpc::{ client, context, server::{self, Channel}, }; /// 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 World { async fn hello(name: String) -> String; } /// This is the type that implements the generated World trait. It is the business logic /// and is used to start the server. #[derive(Clone)] struct HelloServer; impl World for HelloServer { async fn hello(self, _: context::Context, name: String) -> String { format!("Hello, {name}!") } } async fn spawn(fut: impl Future + Send + 'static) { tokio::spawn(fut); } #[tokio::main] async fn main() -> anyhow::Result<()> { let (client_transport, server_transport) = tarpc::transport::channel::unbounded(); let server = server::BaseChannel::with_defaults(server_transport); tokio::spawn(server.execute(HelloServer.serve()).for_each(spawn)); // WorldClient is generated by the #[tarpc::service] attribute. It has a constructor `new` // that takes a config and any Transport as input. let client = WorldClient::new(client::Config::default(), client_transport).spawn(); // The client has an RPC method for each RPC defined in the annotated trait. 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(()) }