]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/thrift/lib/rs/test/src/bin/kitchen_sink_server.rs
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / lib / rs / test / src / bin / kitchen_sink_server.rs
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 extern crate kitchen_sink;
21 extern crate thrift;
22
23 use thrift::protocol::{
24 TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory, TCompactInputProtocolFactory,
25 TCompactOutputProtocolFactory, TInputProtocolFactory, TOutputProtocolFactory,
26 };
27 use thrift::server::TServer;
28 use thrift::transport::{
29 TFramedReadTransportFactory, TFramedWriteTransportFactory, TReadTransportFactory,
30 TWriteTransportFactory,
31 };
32
33 use kitchen_sink::base_one::Noodle;
34 use kitchen_sink::base_two::{
35 BrothType, Napkin, NapkinServiceSyncHandler, Ramen, RamenServiceSyncHandler,
36 };
37 use kitchen_sink::midlayer::{
38 Dessert, Meal, MealServiceSyncHandler, MealServiceSyncProcessor, Pie,
39 };
40 use kitchen_sink::recursive;
41 use kitchen_sink::ultimate::FullMealAndDrinksServiceSyncHandler;
42 use kitchen_sink::ultimate::{
43 Drink, FullMeal, FullMealAndDrinks, FullMealAndDrinksServiceSyncProcessor,
44 FullMealServiceSyncHandler,
45 };
46
47 fn main() {
48 match run() {
49 Ok(()) => println!("kitchen sink server completed successfully"),
50 Err(e) => {
51 println!("kitchen sink server failed with error {:?}", e);
52 std::process::exit(1);
53 }
54 }
55 }
56
57 fn run() -> thrift::Result<()> {
58 let matches = clap_app!(rust_kitchen_sink_server =>
59 (version: "0.1.0")
60 (author: "Apache Thrift Developers <dev@thrift.apache.org>")
61 (about: "Thrift Rust kitchen sink test server")
62 (@arg port: --port +takes_value "port on which the test server listens")
63 (@arg protocol: --protocol +takes_value "Thrift protocol implementation to use (\"binary\", \"compact\")")
64 (@arg service: --service +takes_value "Service type to contact (\"part\", \"full\", \"recursive\")")
65 )
66 .get_matches();
67
68 let port = value_t!(matches, "port", u16).unwrap_or(9090);
69 let protocol = matches.value_of("protocol").unwrap_or("compact");
70 let service = matches.value_of("service").unwrap_or("part");
71 let listen_address = format!("127.0.0.1:{}", port);
72
73 println!("binding to {}", listen_address);
74
75 let r_transport_factory = TFramedReadTransportFactory::new();
76 let w_transport_factory = TFramedWriteTransportFactory::new();
77
78 let (i_protocol_factory, o_protocol_factory): (
79 Box<TInputProtocolFactory>,
80 Box<TOutputProtocolFactory>,
81 ) = match &*protocol {
82 "binary" => (
83 Box::new(TBinaryInputProtocolFactory::new()),
84 Box::new(TBinaryOutputProtocolFactory::new()),
85 ),
86 "compact" => (
87 Box::new(TCompactInputProtocolFactory::new()),
88 Box::new(TCompactOutputProtocolFactory::new()),
89 ),
90 unknown => {
91 return Err(format!("unsupported transport type {}", unknown).into());
92 }
93 };
94
95 // FIXME: should processor be boxed as well?
96 //
97 // [sigh] I hate Rust generics implementation
98 //
99 // I would have preferred to build a server here, return it, and then do
100 // the common listen-and-handle stuff, but since the server doesn't have a
101 // common type (because each match arm instantiates a server with a
102 // different processor) this isn't possible.
103 //
104 // Since what I'm doing is uncommon I'm just going to duplicate the code
105 match &*service {
106 "part" => run_meal_server(
107 &listen_address,
108 r_transport_factory,
109 i_protocol_factory,
110 w_transport_factory,
111 o_protocol_factory,
112 ),
113 "full" => run_full_meal_server(
114 &listen_address,
115 r_transport_factory,
116 i_protocol_factory,
117 w_transport_factory,
118 o_protocol_factory,
119 ),
120 "recursive" => run_recursive_server(
121 &listen_address,
122 r_transport_factory,
123 i_protocol_factory,
124 w_transport_factory,
125 o_protocol_factory,
126 ),
127 unknown => Err(format!("unsupported service type {}", unknown).into()),
128 }
129 }
130
131 fn run_meal_server<RTF, IPF, WTF, OPF>(
132 listen_address: &str,
133 r_transport_factory: RTF,
134 i_protocol_factory: IPF,
135 w_transport_factory: WTF,
136 o_protocol_factory: OPF,
137 ) -> thrift::Result<()>
138 where
139 RTF: TReadTransportFactory + 'static,
140 IPF: TInputProtocolFactory + 'static,
141 WTF: TWriteTransportFactory + 'static,
142 OPF: TOutputProtocolFactory + 'static,
143 {
144 let processor = MealServiceSyncProcessor::new(PartHandler {});
145 let mut server = TServer::new(
146 r_transport_factory,
147 i_protocol_factory,
148 w_transport_factory,
149 o_protocol_factory,
150 processor,
151 1,
152 );
153
154 server.listen(listen_address)
155 }
156
157 fn run_full_meal_server<RTF, IPF, WTF, OPF>(
158 listen_address: &str,
159 r_transport_factory: RTF,
160 i_protocol_factory: IPF,
161 w_transport_factory: WTF,
162 o_protocol_factory: OPF,
163 ) -> thrift::Result<()>
164 where
165 RTF: TReadTransportFactory + 'static,
166 IPF: TInputProtocolFactory + 'static,
167 WTF: TWriteTransportFactory + 'static,
168 OPF: TOutputProtocolFactory + 'static,
169 {
170 let processor = FullMealAndDrinksServiceSyncProcessor::new(FullHandler {});
171 let mut server = TServer::new(
172 r_transport_factory,
173 i_protocol_factory,
174 w_transport_factory,
175 o_protocol_factory,
176 processor,
177 1,
178 );
179
180 server.listen(listen_address)
181 }
182
183 struct PartHandler;
184
185 impl MealServiceSyncHandler for PartHandler {
186 fn handle_meal(&self) -> thrift::Result<Meal> {
187 println!("part: handling meal call");
188 Ok(meal())
189 }
190 }
191
192 impl RamenServiceSyncHandler for PartHandler {
193 fn handle_ramen(&self, _: i32) -> thrift::Result<Ramen> {
194 println!("part: handling ramen call");
195 Ok(ramen())
196 }
197 }
198
199 impl NapkinServiceSyncHandler for PartHandler {
200 fn handle_napkin(&self) -> thrift::Result<Napkin> {
201 println!("part: handling napkin call");
202 Ok(napkin())
203 }
204 }
205
206 // full service
207 //
208
209 struct FullHandler;
210
211 impl FullMealAndDrinksServiceSyncHandler for FullHandler {
212 fn handle_full_meal_and_drinks(&self) -> thrift::Result<FullMealAndDrinks> {
213 println!("full_meal_and_drinks: handling full meal and drinks call");
214 Ok(FullMealAndDrinks::new(full_meal(), Drink::CanadianWhisky))
215 }
216
217 fn handle_best_pie(&self) -> thrift::Result<Pie> {
218 println!("full_meal_and_drinks: handling pie call");
219 Ok(Pie::MississippiMud) // I prefer Pie::Pumpkin, but I have to check that casing works
220 }
221 }
222
223 impl FullMealServiceSyncHandler for FullHandler {
224 fn handle_full_meal(&self) -> thrift::Result<FullMeal> {
225 println!("full: handling full meal call");
226 Ok(full_meal())
227 }
228 }
229
230 impl MealServiceSyncHandler for FullHandler {
231 fn handle_meal(&self) -> thrift::Result<Meal> {
232 println!("full: handling meal call");
233 Ok(meal())
234 }
235 }
236
237 impl RamenServiceSyncHandler for FullHandler {
238 fn handle_ramen(&self, _: i32) -> thrift::Result<Ramen> {
239 println!("full: handling ramen call");
240 Ok(ramen())
241 }
242 }
243
244 impl NapkinServiceSyncHandler for FullHandler {
245 fn handle_napkin(&self) -> thrift::Result<Napkin> {
246 println!("full: handling napkin call");
247 Ok(napkin())
248 }
249 }
250
251 fn full_meal() -> FullMeal {
252 FullMeal::new(meal(), Dessert::Port("Graham's Tawny".to_owned()))
253 }
254
255 fn meal() -> Meal {
256 Meal::new(noodle(), ramen())
257 }
258
259 fn noodle() -> Noodle {
260 Noodle::new("spelt".to_owned(), 100)
261 }
262
263 fn ramen() -> Ramen {
264 Ramen::new("Mr Ramen".to_owned(), 72, BrothType::Miso)
265 }
266
267 fn napkin() -> Napkin {
268 Napkin {}
269 }
270
271 fn run_recursive_server<RTF, IPF, WTF, OPF>(
272 listen_address: &str,
273 r_transport_factory: RTF,
274 i_protocol_factory: IPF,
275 w_transport_factory: WTF,
276 o_protocol_factory: OPF,
277 ) -> thrift::Result<()>
278 where
279 RTF: TReadTransportFactory + 'static,
280 IPF: TInputProtocolFactory + 'static,
281 WTF: TWriteTransportFactory + 'static,
282 OPF: TOutputProtocolFactory + 'static,
283 {
284 let processor = recursive::TestServiceSyncProcessor::new(RecursiveTestServerHandler {});
285 let mut server = TServer::new(
286 r_transport_factory,
287 i_protocol_factory,
288 w_transport_factory,
289 o_protocol_factory,
290 processor,
291 1,
292 );
293
294 server.listen(listen_address)
295 }
296
297 struct RecursiveTestServerHandler;
298 impl recursive::TestServiceSyncHandler for RecursiveTestServerHandler {
299 fn handle_echo_tree(&self, tree: recursive::RecTree) -> thrift::Result<recursive::RecTree> {
300 println!("{:?}", tree);
301 Ok(tree)
302 }
303
304 fn handle_echo_list(&self, lst: recursive::RecList) -> thrift::Result<recursive::RecList> {
305 println!("{:?}", lst);
306 Ok(lst)
307 }
308
309 fn handle_echo_co_rec(&self, item: recursive::CoRec) -> thrift::Result<recursive::CoRec> {
310 println!("{:?}", item);
311 Ok(item)
312 }
313 }