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