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 #[macro_use]
19 extern crate clap;
20
21 extern crate thrift;
22 extern crate thrift_tutorial;
23
24 use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol};
25 use thrift::transport::{ReadHalf, TFramedReadTransport, TFramedWriteTransport, TIoChannel,
26 TTcpChannel, WriteHalf};
27
28 use thrift_tutorial::shared::TSharedServiceSyncClient;
29 use thrift_tutorial::tutorial::{CalculatorSyncClient, Operation, TCalculatorSyncClient, Work};
30
main()31 fn main() {
32 match run() {
33 Ok(()) => println!("tutorial client ran successfully"),
34 Err(e) => {
35 println!("tutorial client failed with error {:?}", e);
36 std::process::exit(1);
37 }
38 }
39 }
40
run() -> thrift::Result<()>41 fn run() -> thrift::Result<()> {
42 let options = clap_app!(rust_tutorial_client =>
43 (version: "0.1.0")
44 (author: "Apache Thrift Developers <dev@thrift.apache.org>")
45 (about: "Thrift Rust tutorial client")
46 (@arg host: --host +takes_value "host on which the tutorial server listens")
47 (@arg port: --port +takes_value "port on which the tutorial server listens")
48 );
49 let matches = options.get_matches();
50
51 // get any passed-in args or the defaults
52 let host = matches.value_of("host").unwrap_or("127.0.0.1");
53 let port = value_t!(matches, "port", u16).unwrap_or(9090);
54
55 // build our client and connect to the host:port
56 let mut client = new_client(host, port)?;
57
58 // alright!
59 // let's start making some calls
60
61 // let's start with a ping; the server should respond
62 println!("ping!");
63 client.ping()?;
64
65 // simple add
66 println!("add");
67 let res = client.add(1, 2)?;
68 println!("added 1, 2 and got {}", res);
69
70 let logid = 32;
71
72 // let's do...a multiply!
73 let res = client
74 .calculate(logid, Work::new(7, 8, Operation::MULTIPLY, None))?;
75 println!("multiplied 7 and 8 and got {}", res);
76
77 // let's get the log for it
78 let res = client.get_struct(32)?;
79 println!("got log {:?} for operation {}", res, logid);
80
81 // ok - let's be bad :(
82 // do a divide by 0
83 // logid doesn't matter; won't be recorded
84 let res = client.calculate(77, Work::new(2, 0, Operation::DIVIDE, "we bad".to_owned()));
85
86 // we should have gotten an exception back
87 match res {
88 Ok(v) => panic!("should not have succeeded with result {}", v),
89 Err(e) => println!("divide by zero failed with error {:?}", e),
90 }
91
92 // let's do a one-way call
93 println!("zip");
94 client.zip()?;
95
96 // and then close out with a final ping
97 println!("ping!");
98 client.ping()?;
99
100 Ok(())
101 }
102
103 type ClientInputProtocol = TCompactInputProtocol<TFramedReadTransport<ReadHalf<TTcpChannel>>>;
104 type ClientOutputProtocol = TCompactOutputProtocol<TFramedWriteTransport<WriteHalf<TTcpChannel>>>;
105
new_client( host: &str, port: u16, ) -> thrift::Result<CalculatorSyncClient<ClientInputProtocol, ClientOutputProtocol>>106 fn new_client
107 (
108 host: &str,
109 port: u16,
110 ) -> thrift::Result<CalculatorSyncClient<ClientInputProtocol, ClientOutputProtocol>> {
111 let mut c = TTcpChannel::new();
112
113 // open the underlying TCP stream
114 println!("connecting to tutorial server on {}:{}", host, port);
115 c.open(&format!("{}:{}", host, port))?;
116
117 // clone the TCP channel into two halves, one which
118 // we'll use for reading, the other for writing
119 let (i_chan, o_chan) = c.split()?;
120
121 // wrap the raw sockets (slow) with a buffered transport of some kind
122 let i_tran = TFramedReadTransport::new(i_chan);
123 let o_tran = TFramedWriteTransport::new(o_chan);
124
125 // now create the protocol implementations
126 let i_prot = TCompactInputProtocol::new(i_tran);
127 let o_prot = TCompactOutputProtocol::new(o_tran);
128
129 // we're done!
130 Ok(CalculatorSyncClient::new(i_prot, o_prot))
131 }
132