xref: /tonic/examples/src/routeguide/client.rs (revision ea7fe66b)
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         while let time = interval.tick().await {
69             let elapsed = time.duration_since(start);
70             let note = RouteNote {
71                 location: Some(Point {
72                     latitude: 409146138 + elapsed.as_secs() as i32,
73                     longitude: -746188906,
74                 }),
75                 message: format!("at {:?}", elapsed),
76             };
77 
78             yield note;
79         }
80     };
81 
82     let response = client.route_chat(Request::new(outbound)).await?;
83     let mut inbound = response.into_inner();
84 
85     while let Some(note) = inbound.message().await? {
86         println!("NOTE = {:?}", note);
87     }
88 
89     Ok(())
90 }
91 
92 #[tokio::main]
93 async fn main() -> Result<(), Box<dyn std::error::Error>> {
94     let mut client = RouteGuideClient::connect("http://[::1]:10000").await?;
95 
96     println!("*** SIMPLE RPC ***");
97     let response = client
98         .get_feature(Request::new(Point {
99             latitude: 409_146_138,
100             longitude: -746_188_906,
101         }))
102         .await?;
103     println!("RESPONSE = {:?}", response);
104 
105     println!("\n*** SERVER STREAMING ***");
106     print_features(&mut client).await?;
107 
108     println!("\n*** CLIENT STREAMING ***");
109     run_record_route(&mut client).await?;
110 
111     println!("\n*** BIDIRECTIONAL STREAMING ***");
112     run_route_chat(&mut client).await?;
113 
114     Ok(())
115 }
116 
117 fn random_point(rng: &mut ThreadRng) -> Point {
118     let latitude = (rng.gen_range(0, 180) - 90) * 10_000_000;
119     let longitude = (rng.gen_range(0, 360) - 180) * 10_000_000;
120     Point {
121         latitude,
122         longitude,
123     }
124 }
125