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
22 extern crate thrift_tutorial
;
24 use std
::collections
::HashMap
;
25 use std
::convert
::{From, Into}
;
26 use std
::default::Default
;
29 use thrift
::protocol
::{TCompactInputProtocolFactory, TCompactOutputProtocolFactory}
;
30 use thrift
::server
::TServer
;
32 use thrift
::transport
::{TFramedReadTransportFactory, TFramedWriteTransportFactory}
;
33 use thrift_tutorial
::shared
::{SharedServiceSyncHandler, SharedStruct}
;
34 use thrift_tutorial
::tutorial
::{CalculatorSyncHandler, CalculatorSyncProcessor}
;
35 use thrift_tutorial
::tutorial
::{InvalidOperation, Operation, Work}
;
39 Ok(()) => println
!("tutorial server ran successfully"),
41 println
!("tutorial server failed with error {:?}", e
);
42 std
::process
::exit(1);
47 fn run() -> thrift
::Result
<()> {
48 let options
= clap_app
!(rust_tutorial_server
=>
50 (author
: "Apache Thrift Developers <dev@thrift.apache.org>")
51 (about
: "Thrift Rust tutorial server")
52 (@arg port
: --port
+takes_value
"port on which the tutorial server listens")
54 let matches
= options
.get_matches();
56 let port
= value_t
!(matches
, "port", u16).unwrap_or(9090);
57 let listen_address
= format
!("127.0.0.1:{}", port
);
59 println
!("binding to {}", listen_address
);
61 let i_tran_fact
= TFramedReadTransportFactory
::new();
62 let i_prot_fact
= TCompactInputProtocolFactory
::new();
64 let o_tran_fact
= TFramedWriteTransportFactory
::new();
65 let o_prot_fact
= TCompactOutputProtocolFactory
::new();
67 // demux incoming messages
68 let processor
= CalculatorSyncProcessor
::new(CalculatorServer
{
72 // create the server and start listening
73 let mut server
= TServer
::new(
82 server
.listen(&listen_address
)
85 /// Handles incoming Calculator service calls.
86 struct CalculatorServer
{
87 log
: Mutex
<HashMap
<i32, SharedStruct
>>,
90 impl Default
for CalculatorServer
{
91 fn default() -> CalculatorServer
{
93 log
: Mutex
::new(HashMap
::new()),
98 // since Calculator extends SharedService we have to implement the
99 // handler for both traits.
102 // SharedService handler
103 impl SharedServiceSyncHandler
for CalculatorServer
{
104 fn handle_get_struct(&self, key
: i32) -> thrift
::Result
<SharedStruct
> {
105 let log
= self.log
.lock().unwrap();
108 .ok_or_else(|| format
!("could not find log for key {}", key
).into())
112 // Calculator handler
113 impl CalculatorSyncHandler
for CalculatorServer
{
114 fn handle_ping(&self) -> thrift
::Result
<()> {
119 fn handle_add(&self, num1
: i32, num2
: i32) -> thrift
::Result
<i32> {
120 println
!("handling add: n1:{} n2:{}", num1
, num2
);
124 fn handle_calculate(&self, logid
: i32, w
: Work
) -> thrift
::Result
<i32> {
125 println
!("handling calculate: l:{}, w:{:?}", logid
, w
);
127 let res
= if let Some(ref op
) = w
.op
{
128 if w
.num1
.is_none() || w
.num2
.is_none() {
129 Err(InvalidOperation
{
130 what_op
: Some(*op
as i32),
131 why
: Some("no operands specified".to_owned()),
134 // so that I don't have to call unwrap() multiple times below
135 let num1
= w
.num1
.as_ref().expect("operands checked");
136 let num2
= w
.num2
.as_ref().expect("operands checked");
139 Operation
::Add
=> Ok(num1
+ num2
),
140 Operation
::Subtract
=> Ok(num1
- num2
),
141 Operation
::Multiply
=> Ok(num1
* num2
),
142 Operation
::Divide
=> {
144 Err(InvalidOperation
{
145 what_op
: Some(*op
as i32),
146 why
: Some("divide by 0".to_owned()),
155 Err(InvalidOperation
::new(
157 "no operation specified".to_owned(),
161 // if the operation was successful log it
162 if let Ok(ref v
) = res
{
163 let mut log
= self.log
.lock().unwrap();
164 log
.insert(logid
, SharedStruct
::new(logid
, format
!("{}", v
)));
167 // the try! macro automatically maps errors
168 // but, since we aren't using that here we have to map errors manually
170 // exception structs defined in the IDL have an auto-generated
171 // impl of From::from
172 res
.map_err(From
::from
)
175 fn handle_zip(&self) -> thrift
::Result
<()> {
176 println
!("handling zip");