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
9 // http://www.apache.org/licenses/LICENSE-2.0
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
21 extern crate kitchen_sink
;
24 use std
::convert
::Into
;
26 use kitchen_sink
::base_two
::{TNapkinServiceSyncClient, TRamenServiceSyncClient}
;
27 use kitchen_sink
::midlayer
::{MealServiceSyncClient, TMealServiceSyncClient}
;
28 use kitchen_sink
::recursive
;
29 use kitchen_sink
::recursive
::{CoRec, CoRec2, RecList, RecTree, TTestServiceSyncClient}
;
30 use kitchen_sink
::ultimate
::{FullMealServiceSyncClient, TFullMealServiceSyncClient}
;
31 use thrift
::protocol
::{
32 TBinaryInputProtocol
, TBinaryOutputProtocol
, TCompactInputProtocol
, TCompactOutputProtocol
,
33 TInputProtocol
, TOutputProtocol
,
35 use thrift
::transport
::{
36 ReadHalf
, TFramedReadTransport
, TFramedWriteTransport
, TIoChannel
, TTcpChannel
, WriteHalf
,
41 Ok(()) => println
!("kitchen sink client completed successfully"),
43 println
!("kitchen sink client failed with error {:?}", e
);
44 std
::process
::exit(1);
49 fn run() -> thrift
::Result
<()> {
50 let matches
= clap_app
!(rust_kitchen_sink_client
=>
52 (author
: "Apache Thrift Developers <dev@thrift.apache.org>")
53 (about
: "Thrift Rust kitchen sink client")
54 (@arg host
: --host
+takes_value
"Host on which the Thrift test server is located")
55 (@arg port
: --port
+takes_value
"Port on which the Thrift test server is listening")
56 (@arg protocol
: --protocol
+takes_value
"Thrift protocol implementation to use (\"binary\", \"compact\")")
57 (@arg service
: --service
+takes_value
"Service type to contact (\"part\", \"full\", \"recursive\")")
61 let host
= matches
.value_of("host").unwrap_or("127.0.0.1");
62 let port
= value_t
!(matches
, "port", u16).unwrap_or(9090);
63 let protocol
= matches
.value_of("protocol").unwrap_or("compact");
64 let service
= matches
.value_of("service").unwrap_or("part");
66 let (i_chan
, o_chan
) = tcp_channel(host
, port
)?
;
67 let (i_tran
, o_tran
) = (
68 TFramedReadTransport
::new(i_chan
),
69 TFramedWriteTransport
::new(o_chan
),
72 let (i_prot
, o_prot
): (Box
<TInputProtocol
>, Box
<TOutputProtocol
>) = match protocol
{
74 Box
::new(TBinaryInputProtocol
::new(i_tran
, true)),
75 Box
::new(TBinaryOutputProtocol
::new(o_tran
, true)),
78 Box
::new(TCompactInputProtocol
::new(i_tran
)),
79 Box
::new(TCompactOutputProtocol
::new(o_tran
)),
81 unmatched
=> return Err(format
!("unsupported protocol {}", unmatched
).into()),
84 run_client(service
, i_prot
, o_prot
)
89 i_prot
: Box
<TInputProtocol
>,
90 o_prot
: Box
<TOutputProtocol
>,
91 ) -> thrift
::Result
<()> {
93 "full" => exec_full_meal_client(i_prot
, o_prot
),
94 "part" => exec_meal_client(i_prot
, o_prot
),
95 "recursive" => exec_recursive_client(i_prot
, o_prot
),
96 _
=> Err(thrift
::Error
::from(format
!(
97 "unknown service type {}",
106 ) -> thrift
::Result
<(ReadHalf
<TTcpChannel
>, WriteHalf
<TTcpChannel
>)> {
107 let mut c
= TTcpChannel
::new();
108 c
.open(&format
!("{}:{}", host
, port
))?
;
113 i_prot
: Box
<TInputProtocol
>,
114 o_prot
: Box
<TOutputProtocol
>,
115 ) -> thrift
::Result
<()> {
116 let mut client
= MealServiceSyncClient
::new(i_prot
, o_prot
);
118 // client.full_meal(); // <-- IMPORTANT: if you uncomment this, compilation *should* fail
119 // this is because the MealService struct does not contain the appropriate service marker
121 // only the following three calls work
122 execute_call("part", "ramen", || client
.ramen(50)).map(|_
| ())?
;
123 execute_call("part", "meal", || client
.meal()).map(|_
| ())?
;
124 execute_call("part", "napkin", || client
.napkin()).map(|_
| ())?
;
129 fn exec_full_meal_client(
130 i_prot
: Box
<TInputProtocol
>,
131 o_prot
: Box
<TOutputProtocol
>,
132 ) -> thrift
::Result
<()> {
133 let mut client
= FullMealServiceSyncClient
::new(i_prot
, o_prot
);
135 execute_call("full", "ramen", || client
.ramen(100)).map(|_
| ())?
;
136 execute_call("full", "meal", || client
.meal()).map(|_
| ())?
;
137 execute_call("full", "napkin", || client
.napkin()).map(|_
| ())?
;
138 execute_call("full", "full meal", || client
.full_meal()).map(|_
| ())?
;
143 fn exec_recursive_client(
144 i_prot
: Box
<TInputProtocol
>,
145 o_prot
: Box
<TOutputProtocol
>,
146 ) -> thrift
::Result
<()> {
147 let mut client
= recursive
::TestServiceSyncClient
::new(i_prot
, o_prot
);
150 children
: Some(vec
![Box
::new(RecTree
{
166 let expected_tree
= RecTree
{
167 children
: Some(vec
![Box
::new(RecTree
{
170 children
: Some(Vec
::new()), // remote returns an empty list
174 children
: Some(Vec
::new()), // remote returns an empty list
183 let returned_tree
= execute_call("recursive", "echo_tree", || client
.echo_tree(tree
.clone()))?
;
184 if returned_tree
!= expected_tree
{
186 "mismatched recursive tree {:?} {:?}",
187 expected_tree
, returned_tree
193 nextitem
: Some(Box
::new(RecList
{
194 nextitem
: Some(Box
::new(RecList
{
202 let returned_list
= execute_call("recursive", "echo_list", || client
.echo_list(list
.clone()))?
;
203 if returned_list
!= list
{
204 return Err(format
!("mismatched recursive list {:?} {:?}", list
, returned_list
).into());
208 other
: Some(Box
::new(CoRec2
{
210 other
: Some(Box
::new(CoRec2 { other: None }
)),
214 let returned_co_rec
= execute_call("recursive", "echo_co_rec", || {
215 client
.echo_co_rec(co_rec
.clone())
217 if returned_co_rec
!= co_rec
{
218 return Err(format
!("mismatched co_rec {:?} {:?}", co_rec
, returned_co_rec
).into());
224 fn execute_call
<F
, R
>(service_type
: &str, call_name
: &str, mut f
: F
) -> thrift
::Result
<R
>
226 F
: FnMut() -> thrift
::Result
<R
>,
231 Ok(_
) => println
!("{}: completed {} call", service_type
, call_name
),
232 Err(ref e
) => println
!(
233 "{}: failed {} call with error {:?}",
234 service_type
, call_name
, e