xref: /tonic/examples/src/routeguide/client.rs (revision a562a3ce)
1 use std::error::Error;
2 use std::time::Duration;
3 
4 use futures::stream;
5 use rand::rngs::ThreadRng;
6 use rand::Rng;
7 use tokio::time;
8 use tonic::transport::Channel;
9 use tonic::Request;
10 
11 use routeguide::route_guide_client::RouteGuideClient;
12 use routeguide::{Point, Rectangle, RouteNote};
13 
14 pub mod routeguide {
15     tonic::include_proto!("routeguide");
16 }
17 
18 async fn print_features(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
19     let rectangle = Rectangle {
20         lo: Some(Point {
21             latitude: 400_000_000,
22             longitude: -750_000_000,
23         }),
24         hi: Some(Point {
25             latitude: 420_000_000,
26             longitude: -730_000_000,
27         }),
28     };
29 
30     let mut stream = client
31         .list_features(Request::new(rectangle))
32         .await?
33         .into_inner();
34 
35     while let Some(feature) = stream.message().await? {
36         println!("NOTE = {:?}", feature);
37     }
38 
39     Ok(())
40 }
41 
42 async fn run_record_route(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
43     let mut rng = rand::thread_rng();
44     let point_count: i32 = rng.gen_range(2..100);
45 
46     let mut points = vec![];
47     for _ in 0..=point_count {
48         points.push(random_point(&mut rng))
49     }
50 
51     println!("Traversing {} points", points.len());
52     let request = Request::new(stream::iter(points));
53 
54     match client.record_route(request).await {
55         Ok(response) => println!("SUMMARY: {:?}", response.into_inner()),
56         Err(e) => println!("something went wrong: {:?}", e),
57     }
58 
59     Ok(())
60 }
61 
62 async fn run_route_chat(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
63     let start = time::Instant::now();
64 
65     let outbound = async_stream::stream! {
66         let mut interval = time::interval(Duration::from_secs(1));
67 
68         loop {
69             let time = interval.tick().await;
70             let elapsed = time.duration_since(start);
71             let note = RouteNote {
72                 location: Some(Point {
73                     latitude: 409146138 + elapsed.as_secs() as i32,
74                     longitude: -746188906,
75                 }),
76                 message: format!("at {:?}", elapsed),
77             };
78 
79             yield note;
80         }
81     };
82 
83     let response = client.route_chat(Request::new(outbound)).await?;
84     let mut inbound = response.into_inner();
85 
86     while let Some(note) = inbound.message().await? {
87         println!("NOTE = {:?}", note);
88     }
89 
90     Ok(())
91 }
92 
93 #[tokio::main]
94 async fn main() -> Result<(), Box<dyn std::error::Error>> {
95     let mut client = RouteGuideClient::connect("http://[::1]:10000").await?;
96 
97     println!("*** SIMPLE RPC ***");
98     let response = client
99         .get_feature(Request::new(Point {
100             latitude: 409_146_138,
101             longitude: -746_188_906,
102         }))
103         .await?;
104     println!("RESPONSE = {:?}", response);
105 
106     println!("\n*** SERVER STREAMING ***");
107     print_features(&mut client).await?;
108 
109     println!("\n*** CLIENT STREAMING ***");
110     run_record_route(&mut client).await?;
111 
112     println!("\n*** BIDIRECTIONAL STREAMING ***");
113     run_route_chat(&mut client).await?;
114 
115     Ok(())
116 }
117 
118 fn random_point(rng: &mut ThreadRng) -> Point {
119     let latitude = (rng.gen_range(0..180) - 90) * 10_000_000;
120     let longitude = (rng.gen_range(0..360) - 180) * 10_000_000;
121     Point {
122         latitude,
123         longitude,
124     }
125 }
126