1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17
18 use clap::{clap_app, value_t};
19
20 use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol};
21 use thrift::transport::{
22 ReadHalf, TFramedReadTransport, TFramedWriteTransport, TIoChannel, TTcpChannel, WriteHalf,
23 };
24
25 use thrift_tutorial::shared::TSharedServiceSyncClient;
26 use thrift_tutorial::tutorial::{CalculatorSyncClient, Operation, TCalculatorSyncClient, Work};
27
main()28 fn main() {
29 match run() {
30 Ok(()) => println!("tutorial client ran successfully"),
31 Err(e) => {
32 println!("tutorial client failed with error {:?}", e);
33 std::process::exit(1);
34 }
35 }
36 }
37
run() -> thrift::Result<()>38 fn run() -> thrift::Result<()> {
39 let options = clap_app!(rust_tutorial_client =>
40 (version: "0.1.0")
41 (author: "Apache Thrift Developers <dev@thrift.apache.org>")
42 (about: "Thrift Rust tutorial client")
43 (@arg host: --host +takes_value "host on which the tutorial server listens")
44 (@arg port: --port +takes_value "port on which the tutorial server listens")
45 );
46 let matches = options.get_matches();
47
48 // get any passed-in args or the defaults
49 let host = matches.value_of("host").unwrap_or("127.0.0.1");
50 let port = value_t!(matches, "port", u16).unwrap_or(9090);
51
52 // build our client and connect to the host:port
53 let mut client = new_client(host, port)?;
54
55 // alright!
56 // let's start making some calls
57
58 // let's start with a ping; the server should respond
59 println!("ping!");
60 client.ping()?;
61
62 // simple add
63 println!("add");
64 let res = client.add(1, 2)?;
65 println!("added 1, 2 and got {}", res);
66
67 let logid = 32;
68
69 // let's do...a multiply!
70 let res = client.calculate(logid, Work::new(7, 8, Operation::Multiply, None))?;
71 println!("multiplied 7 and 8 and got {}", res);
72
73 // let's get the log for it
74 let res = client.get_struct(logid /* 32 */)?;
75 println!("got log {:?} for operation {}", res, logid);
76
77 // ok - let's be bad :(
78 // do a divide by 0
79 // logid doesn't matter; won't be recorded
80 let res = client.calculate(77, Work::new(2, 0, Operation::Divide, "we bad".to_owned()));
81
82 // we should have gotten an exception back
83 match res {
84 Ok(v) => panic!("should not have succeeded with result {}", v),
85 Err(e) => println!("divide by zero failed with error {:?}", e),
86 }
87
88 // let's do a one-way call
89 println!("zip");
90 client.zip()?;
91
92 // and then close out with a final ping
93 println!("ping!");
94 client.ping()?;
95
96 Ok(())
97 }
98
99 type ClientInputProtocol = TCompactInputProtocol<TFramedReadTransport<ReadHalf<TTcpChannel>>>;
100 type ClientOutputProtocol = TCompactOutputProtocol<TFramedWriteTransport<WriteHalf<TTcpChannel>>>;
101
new_client( host: &str, port: u16, ) -> thrift::Result<CalculatorSyncClient<ClientInputProtocol, ClientOutputProtocol>>102 fn new_client(
103 host: &str,
104 port: u16,
105 ) -> thrift::Result<CalculatorSyncClient<ClientInputProtocol, ClientOutputProtocol>> {
106 let mut c = TTcpChannel::new();
107
108 // open the underlying TCP stream
109 println!("connecting to tutorial server on {}:{}", host, port);
110 c.open(&format!("{}:{}", host, port))?;
111
112 // clone the TCP channel into two halves, one which
113 // we'll use for reading, the other for writing
114 let (i_chan, o_chan) = c.split()?;
115
116 // wrap the raw sockets (slow) with a buffered transport of some kind
117 let i_tran = TFramedReadTransport::new(i_chan);
118 let o_tran = TFramedWriteTransport::new(o_chan);
119
120 // now create the protocol implementations
121 let i_prot = TCompactInputProtocol::new(i_tran);
122 let o_prot = TCompactOutputProtocol::new(o_tran);
123
124 // we're done!
125 Ok(CalculatorSyncClient::new(i_prot, o_prot))
126 }
127