Created
January 26, 2017 17:24
-
-
Save allengeorge/bcb36e7809e78d3218e06c27dcd74df6 to your computer and use it in GitHub Desktop.
Thrift Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Autogenerated by Thrift Compiler (1.0.0-dev) | |
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING | |
#![allow(unused_imports)] | |
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments, type_complexity))] | |
extern crate ordered_float; | |
extern crate thrift; | |
extern crate try_from; | |
use ordered_float::OrderedFloat; | |
use std::cell::RefCell; | |
use std::collections::{BTreeMap, BTreeSet}; | |
use std::convert::From; | |
use std::default::Default; | |
use std::error::Error; | |
use std::fmt; | |
use std::fmt::{Display, Formatter}; | |
use std::rc::Rc; | |
use try_from::TryFrom; | |
use thrift::{ApplicationError, ApplicationErrorKind, ProtocolError, ProtocolErrorKind, TThriftClient}; | |
use thrift::protocol::{TFieldIdentifier, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, TInputProtocol, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType}; | |
use thrift::protocol::field_id; | |
use thrift::protocol::verify_expected_message_type; | |
use thrift::protocol::verify_expected_sequence_number; | |
use thrift::protocol::verify_expected_service_call; | |
use thrift::protocol::verify_required_field_exists; | |
use thrift::server::TProcessor; | |
use shared; | |
///You can define enums, which are just 32 bit integers. Values are optional | |
///and start at 1 if not supplied, C style again. | |
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
pub enum Operation { | |
ADD = 1, | |
SUBTRACT = 2, | |
MULTIPLY = 3, | |
DIVIDE = 4, | |
} | |
impl Operation { | |
pub fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
o_prot.write_i32(*self as i32) | |
} | |
pub fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<Operation> { | |
let enum_value = i_prot.read_i32()?; | |
Operation::try_from(enum_value) } | |
} | |
impl TryFrom<i32> for Operation { | |
type Err = thrift::Error; fn try_from(i: i32) -> Result<Self, Self::Err> { | |
match i { | |
1 => Ok(Operation::ADD), | |
2 => Ok(Operation::SUBTRACT), | |
3 => Ok(Operation::MULTIPLY), | |
4 => Ok(Operation::DIVIDE), | |
_ => { | |
Err( | |
thrift::Error::Protocol( | |
ProtocolError::new( | |
ProtocolErrorKind::InvalidData, | |
format!("cannot convert enum constant {} to Operation", i) | |
) | |
) | |
) | |
}, | |
} | |
} | |
} | |
pub type MyInteger = i32; | |
// | |
// Work | |
// | |
///Structs are the basic complex data structures. They are comprised of fields | |
///which each have an integer identifier, a type, a symbolic name, and an | |
///optional default value. | |
/// | |
///Fields can be declared "optional", which ensures they will not be included | |
///in the serialized output if they aren't set. Note that this requires some | |
///manual management in some languages. | |
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
pub struct Work { | |
pub num1: Option<i32>, | |
pub num2: Option<i32>, | |
pub op: Option<Operation>, | |
pub comment: Option<String>, | |
} | |
impl Work { | |
pub fn new<F1, F2, F3, F4>(num1: F1, num2: F2, op: F3, comment: F4) -> Work where F1: Into<Option<i32>>, F2: Into<Option<i32>>, F3: Into<Option<Operation>>, F4: Into<Option<String>> { | |
Work { | |
num1: num1.into(), | |
num2: num2.into(), | |
op: op.into(), | |
comment: comment.into(), | |
} | |
} | |
pub fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<Work> { | |
i_prot.read_struct_begin()?; | |
let mut f_1: Option<i32> = Some(0); | |
let mut f_2: Option<i32> = Some(0); | |
let mut f_3: Option<Operation> = None; | |
let mut f_4: Option<String> = None; | |
loop { | |
let field_ident = i_prot.read_field_begin()?; | |
if field_ident.field_type == TType::Stop { | |
break; | |
} | |
let field_id = field_id(&field_ident)?; | |
match field_id { | |
1 => { | |
let val = i_prot.read_i32()?; | |
f_1 = Some(val); | |
}, | |
2 => { | |
let val = i_prot.read_i32()?; | |
f_2 = Some(val); | |
}, | |
3 => { | |
let val = Operation::read_from_in_protocol(i_prot)?; | |
f_3 = Some(val); | |
}, | |
4 => { | |
let val = i_prot.read_string()?; | |
f_4 = Some(val); | |
}, | |
_ => { | |
i_prot.skip(field_ident.field_type)?; | |
}, | |
}; | |
i_prot.read_field_end()?; | |
} | |
i_prot.read_struct_end()?; | |
let ret = Work { | |
num1: f_1, | |
num2: f_2, | |
op: f_3, | |
comment: f_4, | |
}; | |
Ok(ret) | |
} | |
pub fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let struct_ident = TStructIdentifier::new("Work"); | |
o_prot.write_struct_begin(&struct_ident)?; | |
if let Some(fld_var) = self.num1 { | |
o_prot.write_field_begin(&TFieldIdentifier::new("num1", TType::I32, 1))?; | |
o_prot.write_i32(fld_var)?; | |
o_prot.write_field_end()?; | |
() | |
} else { | |
() | |
} | |
if let Some(fld_var) = self.num2 { | |
o_prot.write_field_begin(&TFieldIdentifier::new("num2", TType::I32, 2))?; | |
o_prot.write_i32(fld_var)?; | |
o_prot.write_field_end()?; | |
() | |
} else { | |
() | |
} | |
if let Some(ref fld_var) = self.op { | |
o_prot.write_field_begin(&TFieldIdentifier::new("op", TType::I32, 3))?; | |
fld_var.write_to_out_protocol(o_prot)?; | |
o_prot.write_field_end()?; | |
() | |
} else { | |
() | |
} | |
if let Some(ref fld_var) = self.comment { | |
o_prot.write_field_begin(&TFieldIdentifier::new("comment", TType::String, 4))?; | |
o_prot.write_string(fld_var)?; | |
o_prot.write_field_end()?; | |
() | |
} else { | |
() | |
} | |
o_prot.write_field_stop()?; | |
o_prot.write_struct_end() | |
} | |
} | |
impl Default for Work { | |
fn default() -> Self { | |
Work{ | |
num1: Some(0), | |
num2: Some(0), | |
op: None, | |
comment: Some("".to_owned()), | |
} | |
} | |
} | |
// | |
// InvalidOperation | |
// | |
///Structs can also be exceptions, if they are nasty. | |
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
pub struct InvalidOperation { | |
pub what_op: Option<i32>, | |
pub why: Option<String>, | |
} | |
impl InvalidOperation { | |
pub fn new<F1, F2>(what_op: F1, why: F2) -> InvalidOperation where F1: Into<Option<i32>>, F2: Into<Option<String>> { | |
InvalidOperation { | |
what_op: what_op.into(), | |
why: why.into(), | |
} | |
} | |
pub fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<InvalidOperation> { | |
i_prot.read_struct_begin()?; | |
let mut f_1: Option<i32> = Some(0); | |
let mut f_2: Option<String> = Some("".to_owned()); | |
loop { | |
let field_ident = i_prot.read_field_begin()?; | |
if field_ident.field_type == TType::Stop { | |
break; | |
} | |
let field_id = field_id(&field_ident)?; | |
match field_id { | |
1 => { | |
let val = i_prot.read_i32()?; | |
f_1 = Some(val); | |
}, | |
2 => { | |
let val = i_prot.read_string()?; | |
f_2 = Some(val); | |
}, | |
_ => { | |
i_prot.skip(field_ident.field_type)?; | |
}, | |
}; | |
i_prot.read_field_end()?; | |
} | |
i_prot.read_struct_end()?; | |
let ret = InvalidOperation { | |
what_op: f_1, | |
why: f_2, | |
}; | |
Ok(ret) | |
} | |
pub fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let struct_ident = TStructIdentifier::new("InvalidOperation"); | |
o_prot.write_struct_begin(&struct_ident)?; | |
if let Some(fld_var) = self.what_op { | |
o_prot.write_field_begin(&TFieldIdentifier::new("whatOp", TType::I32, 1))?; | |
o_prot.write_i32(fld_var)?; | |
o_prot.write_field_end()?; | |
() | |
} else { | |
() | |
} | |
if let Some(ref fld_var) = self.why { | |
o_prot.write_field_begin(&TFieldIdentifier::new("why", TType::String, 2))?; | |
o_prot.write_string(fld_var)?; | |
o_prot.write_field_end()?; | |
() | |
} else { | |
() | |
} | |
o_prot.write_field_stop()?; | |
o_prot.write_struct_end() | |
} | |
} | |
impl Default for InvalidOperation { | |
fn default() -> Self { | |
InvalidOperation{ | |
what_op: Some(0), | |
why: Some("".to_owned()), | |
} | |
} | |
} | |
impl Error for InvalidOperation { | |
fn description(&self) -> &str { | |
"remote service threw InvalidOperation" | |
} | |
} | |
impl From<InvalidOperation> for thrift::Error { | |
fn from(e: InvalidOperation) -> Self { | |
thrift::Error::User(Box::new(e)) | |
} | |
} | |
impl Display for InvalidOperation { | |
fn fmt(&self, f: &mut Formatter) -> fmt::Result { | |
self.description().fmt(f) | |
} | |
} | |
pub const I_N_T32_C_O_N_S_T_A_N_T: i32 = 9853; | |
pub struct ConstMAPCONSTANT; | |
impl ConstMAPCONSTANT { | |
pub fn const_value() -> BTreeMap<String, String> { | |
{ | |
let mut m: BTreeMap<String, String> = BTreeMap::new(); | |
let k = "hello".to_owned(); | |
let v = "world".to_owned(); | |
m.insert(k, v); | |
let k = "goodnight".to_owned(); | |
let v = "moon".to_owned(); | |
m.insert(k, v); | |
m | |
} | |
} | |
} | |
// | |
// Calculator service client | |
// | |
///Ahh, now onto the cool part, defining a service. Services just need a name | |
///and can optionally inherit from another service using the extends keyword. | |
pub trait TCalculatorSyncClient : shared::TSharedServiceSyncClient { | |
///A method definition looks like C code. It has a return type, arguments, | |
///and optionally a list of exceptions that it may throw. Note that argument | |
///lists and exception lists are specified using the exact same syntax as | |
///field lists in struct or exception definitions. | |
fn ping(&mut self) -> thrift::Result<()>; | |
fn add(&mut self, num1: i32, num2: i32) -> thrift::Result<i32>; | |
fn calculate(&mut self, logid: i32, w: Work) -> thrift::Result<i32>; | |
///This method has a oneway modifier. That means the client only makes | |
///a request and does not listen for any response at all. Oneway methods | |
///must be void. | |
fn zip(&mut self) -> thrift::Result<()>; | |
} | |
pub trait TCalculatorSyncClientMarker {} | |
pub struct CalculatorSyncClient { | |
_i_prot: Box<TInputProtocol>, | |
_o_prot: Box<TOutputProtocol>, | |
_sequence_number: i32, | |
} | |
impl CalculatorSyncClient { | |
pub fn new(input_protocol: Box<TInputProtocol>, output_protocol: Box<TOutputProtocol>) -> CalculatorSyncClient { | |
CalculatorSyncClient { _i_prot: input_protocol, _o_prot: output_protocol, _sequence_number: 0 } | |
} | |
} | |
impl TThriftClient for CalculatorSyncClient { | |
fn i_prot_mut(&mut self) -> &mut TInputProtocol { &mut *self._i_prot } | |
fn o_prot_mut(&mut self) -> &mut TOutputProtocol { &mut *self._o_prot } | |
fn sequence_number(&self) -> i32 { self._sequence_number } | |
fn increment_sequence_number(&mut self) -> i32 { self._sequence_number += 1; self._sequence_number } | |
} | |
impl TCalculatorSyncClientMarker for CalculatorSyncClient {} | |
impl shared::TSharedServiceSyncClientMarker for CalculatorSyncClient {} | |
impl <C: TThriftClient + TCalculatorSyncClientMarker + shared::TSharedServiceSyncClientMarker> TCalculatorSyncClient for C { | |
fn ping(&mut self) -> thrift::Result<()> { | |
( | |
{ | |
self.increment_sequence_number(); | |
let message_ident = TMessageIdentifier::new("ping", TMessageType::Call, self.sequence_number()); | |
let call_args = PingArgs { }; | |
self.o_prot_mut().write_message_begin(&message_ident)?; | |
call_args.write_to_out_protocol(self.o_prot_mut())?; | |
self.o_prot_mut().write_message_end()?; | |
self.o_prot_mut().flush() | |
} | |
)?; | |
{ | |
let message_ident = self.i_prot_mut().read_message_begin()?; | |
verify_expected_sequence_number(self.sequence_number(), message_ident.sequence_number)?; | |
verify_expected_service_call("ping", &message_ident.name)?; | |
if message_ident.message_type == TMessageType::Exception { | |
let remote_error = thrift::Error::read_application_error_from_in_protocol(self.i_prot_mut())?; | |
self.i_prot_mut().read_message_end()?; | |
return Err(thrift::Error::Application(remote_error)) | |
} | |
verify_expected_message_type(TMessageType::Reply, message_ident.message_type)?; | |
let result = PingResult::read_from_in_protocol(self.i_prot_mut())?; | |
self.i_prot_mut().read_message_end()?; | |
result.ok_or() | |
} | |
} | |
fn add(&mut self, num1: i32, num2: i32) -> thrift::Result<i32> { | |
( | |
{ | |
self.increment_sequence_number(); | |
let message_ident = TMessageIdentifier::new("add", TMessageType::Call, self.sequence_number()); | |
let call_args = AddArgs { num1: num1, num2: num2 }; | |
self.o_prot_mut().write_message_begin(&message_ident)?; | |
call_args.write_to_out_protocol(self.o_prot_mut())?; | |
self.o_prot_mut().write_message_end()?; | |
self.o_prot_mut().flush() | |
} | |
)?; | |
{ | |
let message_ident = self.i_prot_mut().read_message_begin()?; | |
verify_expected_sequence_number(self.sequence_number(), message_ident.sequence_number)?; | |
verify_expected_service_call("add", &message_ident.name)?; | |
if message_ident.message_type == TMessageType::Exception { | |
let remote_error = thrift::Error::read_application_error_from_in_protocol(self.i_prot_mut())?; | |
self.i_prot_mut().read_message_end()?; | |
return Err(thrift::Error::Application(remote_error)) | |
} | |
verify_expected_message_type(TMessageType::Reply, message_ident.message_type)?; | |
let result = AddResult::read_from_in_protocol(self.i_prot_mut())?; | |
self.i_prot_mut().read_message_end()?; | |
result.ok_or() | |
} | |
} | |
fn calculate(&mut self, logid: i32, w: Work) -> thrift::Result<i32> { | |
( | |
{ | |
self.increment_sequence_number(); | |
let message_ident = TMessageIdentifier::new("calculate", TMessageType::Call, self.sequence_number()); | |
let call_args = CalculateArgs { logid: logid, w: w }; | |
self.o_prot_mut().write_message_begin(&message_ident)?; | |
call_args.write_to_out_protocol(self.o_prot_mut())?; | |
self.o_prot_mut().write_message_end()?; | |
self.o_prot_mut().flush() | |
} | |
)?; | |
{ | |
let message_ident = self.i_prot_mut().read_message_begin()?; | |
verify_expected_sequence_number(self.sequence_number(), message_ident.sequence_number)?; | |
verify_expected_service_call("calculate", &message_ident.name)?; | |
if message_ident.message_type == TMessageType::Exception { | |
let remote_error = thrift::Error::read_application_error_from_in_protocol(self.i_prot_mut())?; | |
self.i_prot_mut().read_message_end()?; | |
return Err(thrift::Error::Application(remote_error)) | |
} | |
verify_expected_message_type(TMessageType::Reply, message_ident.message_type)?; | |
let result = CalculateResult::read_from_in_protocol(self.i_prot_mut())?; | |
self.i_prot_mut().read_message_end()?; | |
result.ok_or() | |
} | |
} | |
fn zip(&mut self) -> thrift::Result<()> { | |
( | |
{ | |
self.increment_sequence_number(); | |
let message_ident = TMessageIdentifier::new("zip", TMessageType::OneWay, self.sequence_number()); | |
let call_args = ZipArgs { }; | |
self.o_prot_mut().write_message_begin(&message_ident)?; | |
call_args.write_to_out_protocol(self.o_prot_mut())?; | |
self.o_prot_mut().write_message_end()?; | |
self.o_prot_mut().flush() | |
} | |
)?; | |
Ok(()) | |
} | |
} | |
// | |
// Calculator service processor | |
// | |
///Ahh, now onto the cool part, defining a service. Services just need a name | |
///and can optionally inherit from another service using the extends keyword. | |
pub trait CalculatorSyncHandler : shared::SharedServiceSyncHandler { | |
///A method definition looks like C code. It has a return type, arguments, | |
///and optionally a list of exceptions that it may throw. Note that argument | |
///lists and exception lists are specified using the exact same syntax as | |
///field lists in struct or exception definitions. | |
fn handle_ping(&mut self) -> thrift::Result<()>; | |
fn handle_add(&mut self, num1: i32, num2: i32) -> thrift::Result<i32>; | |
fn handle_calculate(&mut self, logid: i32, w: Work) -> thrift::Result<i32>; | |
///This method has a oneway modifier. That means the client only makes | |
///a request and does not listen for any response at all. Oneway methods | |
///must be void. | |
fn handle_zip(&mut self) -> thrift::Result<()>; | |
} | |
pub struct CalculatorSyncProcessor<H: CalculatorSyncHandler> { | |
handler: H, | |
} | |
impl <H: CalculatorSyncHandler> CalculatorSyncProcessor<H> { | |
pub fn new(handler: H) -> CalculatorSyncProcessor<H> { | |
CalculatorSyncProcessor { | |
handler: handler, | |
} | |
} | |
fn process_ping(&mut self, incoming_sequence_number: i32, i_prot: &mut TInputProtocol, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
TCalculatorProcessFunctions::process_ping(&mut self.handler, incoming_sequence_number, i_prot, o_prot) | |
} | |
fn process_add(&mut self, incoming_sequence_number: i32, i_prot: &mut TInputProtocol, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
TCalculatorProcessFunctions::process_add(&mut self.handler, incoming_sequence_number, i_prot, o_prot) | |
} | |
fn process_calculate(&mut self, incoming_sequence_number: i32, i_prot: &mut TInputProtocol, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
TCalculatorProcessFunctions::process_calculate(&mut self.handler, incoming_sequence_number, i_prot, o_prot) | |
} | |
fn process_zip(&mut self, incoming_sequence_number: i32, i_prot: &mut TInputProtocol, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
TCalculatorProcessFunctions::process_zip(&mut self.handler, incoming_sequence_number, i_prot, o_prot) | |
} | |
fn process_get_struct(&mut self, incoming_sequence_number: i32, i_prot: &mut TInputProtocol, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
shared::TSharedServiceProcessFunctions::process_get_struct(&mut self.handler, incoming_sequence_number, i_prot, o_prot) | |
} | |
} | |
pub struct TCalculatorProcessFunctions; | |
impl TCalculatorProcessFunctions { | |
pub fn process_ping<H: CalculatorSyncHandler>(handler: &mut H, incoming_sequence_number: i32, i_prot: &mut TInputProtocol, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let _ = PingArgs::read_from_in_protocol(i_prot)?; | |
match handler.handle_ping() { | |
Ok(_) => { | |
let message_ident = TMessageIdentifier::new("ping", TMessageType::Reply, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
let ret = PingResult { }; | |
ret.write_to_out_protocol(o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
}, | |
Err(e) => { | |
match e { | |
thrift::Error::Application(app_err) => { | |
let message_ident = TMessageIdentifier::new("ping", TMessageType::Exception, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
thrift::Error::write_application_error_to_out_protocol(&app_err, o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
}, | |
_ => { | |
let ret_err = { | |
ApplicationError::new( | |
ApplicationErrorKind::Unknown, | |
e.description() | |
) | |
}; | |
let message_ident = TMessageIdentifier::new("ping", TMessageType::Exception, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
thrift::Error::write_application_error_to_out_protocol(&ret_err, o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
}, | |
} | |
}, | |
} | |
} | |
pub fn process_add<H: CalculatorSyncHandler>(handler: &mut H, incoming_sequence_number: i32, i_prot: &mut TInputProtocol, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let args = AddArgs::read_from_in_protocol(i_prot)?; | |
match handler.handle_add(args.num1, args.num2) { | |
Ok(handler_return) => { | |
let message_ident = TMessageIdentifier::new("add", TMessageType::Reply, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
let ret = AddResult { result_value: Some(handler_return) }; | |
ret.write_to_out_protocol(o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
}, | |
Err(e) => { | |
match e { | |
thrift::Error::Application(app_err) => { | |
let message_ident = TMessageIdentifier::new("add", TMessageType::Exception, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
thrift::Error::write_application_error_to_out_protocol(&app_err, o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
}, | |
_ => { | |
let ret_err = { | |
ApplicationError::new( | |
ApplicationErrorKind::Unknown, | |
e.description() | |
) | |
}; | |
let message_ident = TMessageIdentifier::new("add", TMessageType::Exception, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
thrift::Error::write_application_error_to_out_protocol(&ret_err, o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
}, | |
} | |
}, | |
} | |
} | |
pub fn process_calculate<H: CalculatorSyncHandler>(handler: &mut H, incoming_sequence_number: i32, i_prot: &mut TInputProtocol, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let args = CalculateArgs::read_from_in_protocol(i_prot)?; | |
match handler.handle_calculate(args.logid, args.w) { | |
Ok(handler_return) => { | |
let message_ident = TMessageIdentifier::new("calculate", TMessageType::Reply, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
let ret = CalculateResult { result_value: Some(handler_return), ouch: None }; | |
ret.write_to_out_protocol(o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
}, | |
Err(e) => { | |
match e { | |
thrift::Error::User(usr_err) => { | |
if usr_err.downcast_ref::<InvalidOperation>().is_some() { | |
let err = usr_err.downcast::<InvalidOperation>().expect("downcast already checked"); | |
let ret_err = CalculateResult{ result_value: None, ouch: Some(*err) }; | |
let message_ident = TMessageIdentifier::new("calculate", TMessageType::Reply, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
ret_err.write_to_out_protocol(o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
} else { | |
let ret_err = { | |
ApplicationError::new( | |
ApplicationErrorKind::Unknown, | |
usr_err.description() | |
) | |
}; | |
let message_ident = TMessageIdentifier::new("calculate", TMessageType::Exception, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
thrift::Error::write_application_error_to_out_protocol(&ret_err, o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
} | |
}, | |
thrift::Error::Application(app_err) => { | |
let message_ident = TMessageIdentifier::new("calculate", TMessageType::Exception, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
thrift::Error::write_application_error_to_out_protocol(&app_err, o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
}, | |
_ => { | |
let ret_err = { | |
ApplicationError::new( | |
ApplicationErrorKind::Unknown, | |
e.description() | |
) | |
}; | |
let message_ident = TMessageIdentifier::new("calculate", TMessageType::Exception, incoming_sequence_number); | |
o_prot.write_message_begin(&message_ident)?; | |
thrift::Error::write_application_error_to_out_protocol(&ret_err, o_prot)?; | |
o_prot.write_message_end()?; | |
o_prot.flush() | |
}, | |
} | |
}, | |
} | |
} | |
pub fn process_zip<H: CalculatorSyncHandler>(handler: &mut H, _: i32, i_prot: &mut TInputProtocol, _: &mut TOutputProtocol) -> thrift::Result<()> { | |
let _ = ZipArgs::read_from_in_protocol(i_prot)?; | |
match handler.handle_zip() { | |
Ok(_) => { | |
Ok(()) | |
}, | |
Err(e) => { | |
match e { | |
thrift::Error::Application(app_err) => { | |
Err(thrift::Error::Application(app_err)) | |
}, | |
_ => { | |
let ret_err = { | |
ApplicationError::new( | |
ApplicationErrorKind::Unknown, | |
e.description() | |
) | |
}; | |
Err(thrift::Error::Application(ret_err)) | |
}, | |
} | |
}, | |
} | |
} | |
} | |
impl <H: CalculatorSyncHandler> TProcessor for CalculatorSyncProcessor<H> { | |
fn process(&mut self, i_prot: &mut TInputProtocol, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let message_ident = i_prot.read_message_begin()?; | |
match &*message_ident.name { | |
"ping" => { | |
self.process_ping(message_ident.sequence_number, i_prot, o_prot) | |
}, | |
"add" => { | |
self.process_add(message_ident.sequence_number, i_prot, o_prot) | |
}, | |
"calculate" => { | |
self.process_calculate(message_ident.sequence_number, i_prot, o_prot) | |
}, | |
"zip" => { | |
self.process_zip(message_ident.sequence_number, i_prot, o_prot) | |
}, | |
"getStruct" => { | |
self.process_get_struct(message_ident.sequence_number, i_prot, o_prot) | |
}, | |
method => { | |
Err( | |
thrift::Error::Application( | |
ApplicationError::new( | |
ApplicationErrorKind::UnknownMethod, | |
format!("unknown method {}", method) | |
) | |
) | |
) | |
}, | |
} | |
} | |
} | |
// | |
// PingArgs | |
// | |
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
struct PingArgs { | |
} | |
impl PingArgs { | |
fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<PingArgs> { | |
i_prot.read_struct_begin()?; | |
loop { | |
let field_ident = i_prot.read_field_begin()?; | |
if field_ident.field_type == TType::Stop { | |
break; | |
} | |
let field_id = field_id(&field_ident)?; | |
match field_id { | |
_ => { | |
i_prot.skip(field_ident.field_type)?; | |
}, | |
}; | |
i_prot.read_field_end()?; | |
} | |
i_prot.read_struct_end()?; | |
let ret = PingArgs {}; | |
Ok(ret) | |
} | |
fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let struct_ident = TStructIdentifier::new("ping_args"); | |
o_prot.write_struct_begin(&struct_ident)?; | |
o_prot.write_field_stop()?; | |
o_prot.write_struct_end() | |
} | |
} | |
// | |
// PingResult | |
// | |
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
struct PingResult { | |
} | |
impl PingResult { | |
fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<PingResult> { | |
i_prot.read_struct_begin()?; | |
loop { | |
let field_ident = i_prot.read_field_begin()?; | |
if field_ident.field_type == TType::Stop { | |
break; | |
} | |
let field_id = field_id(&field_ident)?; | |
match field_id { | |
_ => { | |
i_prot.skip(field_ident.field_type)?; | |
}, | |
}; | |
i_prot.read_field_end()?; | |
} | |
i_prot.read_struct_end()?; | |
let ret = PingResult {}; | |
Ok(ret) | |
} | |
fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let struct_ident = TStructIdentifier::new("PingResult"); | |
o_prot.write_struct_begin(&struct_ident)?; | |
o_prot.write_field_stop()?; | |
o_prot.write_struct_end() | |
} | |
fn ok_or(self) -> thrift::Result<()> { | |
Ok(()) | |
} | |
} | |
// | |
// AddArgs | |
// | |
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
struct AddArgs { | |
num1: i32, | |
num2: i32, | |
} | |
impl AddArgs { | |
fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<AddArgs> { | |
i_prot.read_struct_begin()?; | |
let mut f_1: Option<i32> = None; | |
let mut f_2: Option<i32> = None; | |
loop { | |
let field_ident = i_prot.read_field_begin()?; | |
if field_ident.field_type == TType::Stop { | |
break; | |
} | |
let field_id = field_id(&field_ident)?; | |
match field_id { | |
1 => { | |
let val = i_prot.read_i32()?; | |
f_1 = Some(val); | |
}, | |
2 => { | |
let val = i_prot.read_i32()?; | |
f_2 = Some(val); | |
}, | |
_ => { | |
i_prot.skip(field_ident.field_type)?; | |
}, | |
}; | |
i_prot.read_field_end()?; | |
} | |
i_prot.read_struct_end()?; | |
verify_required_field_exists("AddArgs.num1", &f_1)?; | |
verify_required_field_exists("AddArgs.num2", &f_2)?; | |
let ret = AddArgs { | |
num1: f_1.expect("auto-generated code should have checked for presence of required fields"), | |
num2: f_2.expect("auto-generated code should have checked for presence of required fields"), | |
}; | |
Ok(ret) | |
} | |
fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let struct_ident = TStructIdentifier::new("add_args"); | |
o_prot.write_struct_begin(&struct_ident)?; | |
o_prot.write_field_begin(&TFieldIdentifier::new("num1", TType::I32, 1))?; | |
o_prot.write_i32(self.num1)?; | |
o_prot.write_field_end()?; | |
o_prot.write_field_begin(&TFieldIdentifier::new("num2", TType::I32, 2))?; | |
o_prot.write_i32(self.num2)?; | |
o_prot.write_field_end()?; | |
o_prot.write_field_stop()?; | |
o_prot.write_struct_end() | |
} | |
} | |
// | |
// AddResult | |
// | |
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
struct AddResult { | |
result_value: Option<i32>, | |
} | |
impl AddResult { | |
fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<AddResult> { | |
i_prot.read_struct_begin()?; | |
let mut f_0: Option<i32> = None; | |
loop { | |
let field_ident = i_prot.read_field_begin()?; | |
if field_ident.field_type == TType::Stop { | |
break; | |
} | |
let field_id = field_id(&field_ident)?; | |
match field_id { | |
0 => { | |
let val = i_prot.read_i32()?; | |
f_0 = Some(val); | |
}, | |
_ => { | |
i_prot.skip(field_ident.field_type)?; | |
}, | |
}; | |
i_prot.read_field_end()?; | |
} | |
i_prot.read_struct_end()?; | |
let ret = AddResult { | |
result_value: f_0, | |
}; | |
Ok(ret) | |
} | |
fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let struct_ident = TStructIdentifier::new("AddResult"); | |
o_prot.write_struct_begin(&struct_ident)?; | |
if let Some(fld_var) = self.result_value { | |
o_prot.write_field_begin(&TFieldIdentifier::new("result_value", TType::I32, 0))?; | |
o_prot.write_i32(fld_var)?; | |
o_prot.write_field_end()?; | |
() | |
} else { | |
() | |
} | |
o_prot.write_field_stop()?; | |
o_prot.write_struct_end() | |
} | |
fn ok_or(self) -> thrift::Result<i32> { | |
if self.result_value.is_some() { | |
Ok(self.result_value.unwrap()) | |
} else { | |
Err( | |
thrift::Error::Application( | |
ApplicationError::new( | |
ApplicationErrorKind::MissingResult, | |
"no result received for Add" | |
) | |
) | |
) | |
} | |
} | |
} | |
// | |
// CalculateArgs | |
// | |
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
struct CalculateArgs { | |
logid: i32, | |
w: Work, | |
} | |
impl CalculateArgs { | |
fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<CalculateArgs> { | |
i_prot.read_struct_begin()?; | |
let mut f_1: Option<i32> = None; | |
let mut f_2: Option<Work> = None; | |
loop { | |
let field_ident = i_prot.read_field_begin()?; | |
if field_ident.field_type == TType::Stop { | |
break; | |
} | |
let field_id = field_id(&field_ident)?; | |
match field_id { | |
1 => { | |
let val = i_prot.read_i32()?; | |
f_1 = Some(val); | |
}, | |
2 => { | |
let val = Work::read_from_in_protocol(i_prot)?; | |
f_2 = Some(val); | |
}, | |
_ => { | |
i_prot.skip(field_ident.field_type)?; | |
}, | |
}; | |
i_prot.read_field_end()?; | |
} | |
i_prot.read_struct_end()?; | |
verify_required_field_exists("CalculateArgs.logid", &f_1)?; | |
verify_required_field_exists("CalculateArgs.w", &f_2)?; | |
let ret = CalculateArgs { | |
logid: f_1.expect("auto-generated code should have checked for presence of required fields"), | |
w: f_2.expect("auto-generated code should have checked for presence of required fields"), | |
}; | |
Ok(ret) | |
} | |
fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let struct_ident = TStructIdentifier::new("calculate_args"); | |
o_prot.write_struct_begin(&struct_ident)?; | |
o_prot.write_field_begin(&TFieldIdentifier::new("logid", TType::I32, 1))?; | |
o_prot.write_i32(self.logid)?; | |
o_prot.write_field_end()?; | |
o_prot.write_field_begin(&TFieldIdentifier::new("w", TType::Struct, 2))?; | |
self.w.write_to_out_protocol(o_prot)?; | |
o_prot.write_field_end()?; | |
o_prot.write_field_stop()?; | |
o_prot.write_struct_end() | |
} | |
} | |
// | |
// CalculateResult | |
// | |
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
struct CalculateResult { | |
result_value: Option<i32>, | |
ouch: Option<InvalidOperation>, | |
} | |
impl CalculateResult { | |
fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<CalculateResult> { | |
i_prot.read_struct_begin()?; | |
let mut f_0: Option<i32> = None; | |
let mut f_1: Option<InvalidOperation> = None; | |
loop { | |
let field_ident = i_prot.read_field_begin()?; | |
if field_ident.field_type == TType::Stop { | |
break; | |
} | |
let field_id = field_id(&field_ident)?; | |
match field_id { | |
0 => { | |
let val = i_prot.read_i32()?; | |
f_0 = Some(val); | |
}, | |
1 => { | |
let val = InvalidOperation::read_from_in_protocol(i_prot)?; | |
f_1 = Some(val); | |
}, | |
_ => { | |
i_prot.skip(field_ident.field_type)?; | |
}, | |
}; | |
i_prot.read_field_end()?; | |
} | |
i_prot.read_struct_end()?; | |
let ret = CalculateResult { | |
result_value: f_0, | |
ouch: f_1, | |
}; | |
Ok(ret) | |
} | |
fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let struct_ident = TStructIdentifier::new("CalculateResult"); | |
o_prot.write_struct_begin(&struct_ident)?; | |
if let Some(fld_var) = self.result_value { | |
o_prot.write_field_begin(&TFieldIdentifier::new("result_value", TType::I32, 0))?; | |
o_prot.write_i32(fld_var)?; | |
o_prot.write_field_end()?; | |
() | |
} else { | |
() | |
} | |
if let Some(ref fld_var) = self.ouch { | |
o_prot.write_field_begin(&TFieldIdentifier::new("ouch", TType::Struct, 1))?; | |
fld_var.write_to_out_protocol(o_prot)?; | |
o_prot.write_field_end()?; | |
() | |
} else { | |
() | |
} | |
o_prot.write_field_stop()?; | |
o_prot.write_struct_end() | |
} | |
fn ok_or(self) -> thrift::Result<i32> { | |
if self.ouch.is_some() { | |
Err(thrift::Error::User(Box::new(self.ouch.unwrap()))) | |
} else if self.result_value.is_some() { | |
Ok(self.result_value.unwrap()) | |
} else { | |
Err( | |
thrift::Error::Application( | |
ApplicationError::new( | |
ApplicationErrorKind::MissingResult, | |
"no result received for Calculate" | |
) | |
) | |
) | |
} | |
} | |
} | |
// | |
// ZipArgs | |
// | |
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | |
struct ZipArgs { | |
} | |
impl ZipArgs { | |
fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result<ZipArgs> { | |
i_prot.read_struct_begin()?; | |
loop { | |
let field_ident = i_prot.read_field_begin()?; | |
if field_ident.field_type == TType::Stop { | |
break; | |
} | |
let field_id = field_id(&field_ident)?; | |
match field_id { | |
_ => { | |
i_prot.skip(field_ident.field_type)?; | |
}, | |
}; | |
i_prot.read_field_end()?; | |
} | |
i_prot.read_struct_end()?; | |
let ret = ZipArgs {}; | |
Ok(ret) | |
} | |
fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { | |
let struct_ident = TStructIdentifier::new("zip_args"); | |
o_prot.write_struct_begin(&struct_ident)?; | |
o_prot.write_field_stop()?; | |
o_prot.write_struct_end() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
# Thrift Tutorial | |
# Mark Slee (mcslee@facebook.com) | |
# | |
# This file aims to teach you how to use Thrift, in a .thrift file. Neato. The | |
# first thing to notice is that .thrift files support standard shell comments. | |
# This lets you make your thrift file executable and include your Thrift build | |
# step on the top line. And you can place comments like this anywhere you like. | |
# | |
# Before running this file, you will need to have installed the thrift compiler | |
# into /usr/local/bin. | |
/** | |
* The first thing to know about are types. The available types in Thrift are: | |
* | |
* bool Boolean, one byte | |
* i8 (byte) Signed 8-bit integer | |
* i16 Signed 16-bit integer | |
* i32 Signed 32-bit integer | |
* i64 Signed 64-bit integer | |
* double 64-bit floating point value | |
* string String | |
* binary Blob (byte array) | |
* map<t1,t2> Map from one type to another | |
* list<t1> Ordered list of one type | |
* set<t1> Set of unique elements of one type | |
* | |
* Did you also notice that Thrift supports C style comments? | |
*/ | |
// Just in case you were wondering... yes. We support simple C comments too. | |
/** | |
* Thrift files can reference other Thrift files to include common struct | |
* and service definitions. These are found using the current path, or by | |
* searching relative to any paths specified with the -I compiler flag. | |
* | |
* Included objects are accessed using the name of the .thrift file as a | |
* prefix. i.e. shared.SharedObject | |
*/ | |
include "shared.thrift" | |
/** | |
* Thrift files can namespace, package, or prefix their output in various | |
* target languages. | |
*/ | |
namespace cpp tutorial | |
namespace d tutorial | |
namespace dart tutorial | |
namespace java tutorial | |
namespace php tutorial | |
namespace perl tutorial | |
namespace haxe tutorial | |
namespace netcore tutorial | |
/** | |
* Thrift lets you do typedefs to get pretty names for your types. Standard | |
* C style here. | |
*/ | |
typedef i32 MyInteger | |
/** | |
* Thrift also lets you define constants for use across languages. Complex | |
* types and structs are specified using JSON notation. | |
*/ | |
const i32 INT32CONSTANT = 9853 | |
const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'} | |
/** | |
* You can define enums, which are just 32 bit integers. Values are optional | |
* and start at 1 if not supplied, C style again. | |
*/ | |
enum Operation { | |
ADD = 1, | |
SUBTRACT = 2, | |
MULTIPLY = 3, | |
DIVIDE = 4 | |
} | |
/** | |
* Structs are the basic complex data structures. They are comprised of fields | |
* which each have an integer identifier, a type, a symbolic name, and an | |
* optional default value. | |
* | |
* Fields can be declared "optional", which ensures they will not be included | |
* in the serialized output if they aren't set. Note that this requires some | |
* manual management in some languages. | |
*/ | |
struct Work { | |
1: i32 num1 = 0, | |
2: i32 num2, | |
3: Operation op, | |
4: optional string comment, | |
} | |
/** | |
* Structs can also be exceptions, if they are nasty. | |
*/ | |
exception InvalidOperation { | |
1: i32 whatOp, | |
2: string why | |
} | |
/** | |
* Ahh, now onto the cool part, defining a service. Services just need a name | |
* and can optionally inherit from another service using the extends keyword. | |
*/ | |
service Calculator extends shared.SharedService { | |
/** | |
* A method definition looks like C code. It has a return type, arguments, | |
* and optionally a list of exceptions that it may throw. Note that argument | |
* lists and exception lists are specified using the exact same syntax as | |
* field lists in struct or exception definitions. | |
*/ | |
void ping(), | |
i32 add(1:i32 num1, 2:i32 num2), | |
i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), | |
/** | |
* This method has a oneway modifier. That means the client only makes | |
* a request and does not listen for any response at all. Oneway methods | |
* must be void. | |
*/ | |
oneway void zip() | |
} | |
/** | |
* That just about covers the basics. Take a look in the test/ folder for more | |
* detailed examples. After you run this file, your generated code shows up | |
* in folders with names gen-<language>. The generated code isn't too scary | |
* to look at. It even has pretty indentation. | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment