I am using crate 0.16.0
even with a very simple simple .thrift definition .. this crash message occurs even with the latest tutorial code and this super simple .thrift file I think there is some issue
service.rs
// Autogenerated by Thrift Compiler (0.16.0)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#![allow(unused_imports)]
#![allow(unused_extern_crates)]
#![allow(clippy::too_many_arguments, clippy::type_complexity, clippy::vec_box)]
#![cfg_attr(rustfmt, rustfmt_skip)]
use std::cell::RefCell;
use std::collections::{BTreeMap, BTreeSet};
use std::convert::{From, TryFrom};
use std::default::Default;
use std::error::Error;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::rc::Rc;
use thrift::OrderedFloat;
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;
//
// IBSAPIException
//
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct IBSAPIException {
pub error_code: Option<i32>,
pub message: Option<String>,
}
impl IBSAPIException {
pub fn new<F1, F2>(error_code: F1, message: F2) -> IBSAPIException where F1: Into<Option<i32>>, F2: Into<Option<String>> {
IBSAPIException {
error_code: error_code.into(),
message: message.into(),
}
}
pub fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<IBSAPIException> {
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 = IBSAPIException {
error_code: f_1,
message: f_2,
};
Ok(ret)
}
pub fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {
let struct_ident = TStructIdentifier::new("IBSAPIException");
o_prot.write_struct_begin(&struct_ident)?;
if let Some(fld_var) = self.error_code {
o_prot.write_field_begin(&TFieldIdentifier::new("error_code", TType::I32, 1))?;
o_prot.write_i32(fld_var)?;
o_prot.write_field_end()?
}
if let Some(ref fld_var) = self.message {
o_prot.write_field_begin(&TFieldIdentifier::new("message", TType::String, 2))?;
o_prot.write_string(fld_var)?;
o_prot.write_field_end()?
}
o_prot.write_field_stop()?;
o_prot.write_struct_end()
}
}
impl Default for IBSAPIException {
fn default() -> Self {
IBSAPIException{
error_code: Some(0),
message: Some("".to_owned()),
}
}
}
impl Error for IBSAPIException {}
impl From<IBSAPIException> for thrift::Error {
fn from(e: IBSAPIException) -> Self {
thrift::Error::User(Box::new(e))
}
}
impl Display for IBSAPIException {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "remote service threw IBSAPIException")
}
}
//
// ibrokers service client
//
pub trait TIbrokersSyncClient {
fn ping(&mut self) -> thrift::Result<i32>;
fn ib_status(&mut self) -> thrift::Result<Vec<String>>;
}
pub trait TIbrokersSyncClientMarker {}
pub struct IbrokersSyncClient<IP, OP> where IP: TInputProtocol, OP: TOutputProtocol {
_i_prot: IP,
_o_prot: OP,
_sequence_number: i32,
}
impl <IP, OP> IbrokersSyncClient<IP, OP> where IP: TInputProtocol, OP: TOutputProtocol {
pub fn new(input_protocol: IP, output_protocol: OP) -> IbrokersSyncClient<IP, OP> {
IbrokersSyncClient { _i_prot: input_protocol, _o_prot: output_protocol, _sequence_number: 0 }
}
}
impl <IP, OP> TThriftClient for IbrokersSyncClient<IP, OP> where IP: TInputProtocol, OP: TOutputProtocol {
fn i_prot_mut(&mut self) -> &mut dyn TInputProtocol { &mut self._i_prot }
fn o_prot_mut(&mut self) -> &mut dyn 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 <IP, OP> TIbrokersSyncClientMarker for IbrokersSyncClient<IP, OP> where IP: TInputProtocol, OP: TOutputProtocol {}
impl <C: TThriftClient + TIbrokersSyncClientMarker> TIbrokersSyncClient for C {
fn ping(&mut self) -> thrift::Result<i32> {
(
{
self.increment_sequence_number();
let message_ident = TMessageIdentifier::new("ping", TMessageType::Call, self.sequence_number());
let call_args = IbrokersPingArgs { };
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 = IbrokersPingResult::read_from_in_protocol(self.i_prot_mut())?;
self.i_prot_mut().read_message_end()?;
result.ok_or()
}
}
fn ib_status(&mut self) -> thrift::Result<Vec<String>> {
(
{
self.increment_sequence_number();
let message_ident = TMessageIdentifier::new("ib_status", TMessageType::Call, self.sequence_number());
let call_args = IbrokersIbStatusArgs { };
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("ib_status", &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 = IbrokersIbStatusResult::read_from_in_protocol(self.i_prot_mut())?;
self.i_prot_mut().read_message_end()?;
result.ok_or()
}
}
}
//
// ibrokers service processor
//
pub trait IbrokersSyncHandler {
fn handle_ping(&self) -> thrift::Result<i32>;
fn handle_ib_status(&self) -> thrift::Result<Vec<String>>;
}
pub struct IbrokersSyncProcessor<H: IbrokersSyncHandler> {
handler: H,
}
impl <H: IbrokersSyncHandler> IbrokersSyncProcessor<H> {
pub fn new(handler: H) -> IbrokersSyncProcessor<H> {
IbrokersSyncProcessor {
handler,
}
}
fn process_ping(&self, incoming_sequence_number: i32, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {
TIbrokersProcessFunctions::process_ping(&self.handler, incoming_sequence_number, i_prot, o_prot)
}
fn process_ib_status(&self, incoming_sequence_number: i32, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {
TIbrokersProcessFunctions::process_ib_status(&self.handler, incoming_sequence_number, i_prot, o_prot)
}
}
pub struct TIbrokersProcessFunctions;
impl TIbrokersProcessFunctions {
pub fn process_ping<H: IbrokersSyncHandler>(handler: &H, incoming_sequence_number: i32, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {
let _ = IbrokersPingArgs::read_from_in_protocol(i_prot)?;
match handler.handle_ping() {
Ok(handler_return) => {
let message_ident = TMessageIdentifier::new("ping", TMessageType::Reply, incoming_sequence_number);
o_prot.write_message_begin(&message_ident)?;
let ret = IbrokersPingResult { result_value: Some(handler_return), error: 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::<IBSAPIException>().is_some() {
let err = usr_err.downcast::<IBSAPIException>().expect("downcast already checked");
let ret_err = IbrokersPingResult{ result_value: None, error: Some(*err) };
let message_ident = TMessageIdentifier::new("ping", 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.to_string()
)
};
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()
}
},
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.to_string()
)
};
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_ib_status<H: IbrokersSyncHandler>(handler: &H, incoming_sequence_number: i32, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {
let _ = IbrokersIbStatusArgs::read_from_in_protocol(i_prot)?;
match handler.handle_ib_status() {
Ok(handler_return) => {
let message_ident = TMessageIdentifier::new("ib_status", TMessageType::Reply, incoming_sequence_number);
o_prot.write_message_begin(&message_ident)?;
let ret = IbrokersIbStatusResult { result_value: Some(handler_return), error: 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::<IBSAPIException>().is_some() {
let err = usr_err.downcast::<IBSAPIException>().expect("downcast already checked");
let ret_err = IbrokersIbStatusResult{ result_value: None, error: Some(*err) };
let message_ident = TMessageIdentifier::new("ib_status", 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.to_string()
)
};
let message_ident = TMessageIdentifier::new("ib_status", 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("ib_status", 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.to_string()
)
};
let message_ident = TMessageIdentifier::new("ib_status", 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()
},
}
},
}
}
}
impl <H: IbrokersSyncHandler> TProcessor for IbrokersSyncProcessor<H> {
fn process(&self, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {
let message_ident = i_prot.read_message_begin()?;
let res = match &*message_ident.name {
"ping" => {
self.process_ping(message_ident.sequence_number, i_prot, o_prot)
},
"ib_status" => {
self.process_ib_status(message_ident.sequence_number, i_prot, o_prot)
},
method => {
Err(
thrift::Error::Application(
ApplicationError::new(
ApplicationErrorKind::UnknownMethod,
format!("unknown method {}", method)
)
)
)
},
};
thrift::server::handle_process_result(&message_ident, res, o_prot)
}
}
//
// IbrokersPingArgs
//
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct IbrokersPingArgs {
}
impl IbrokersPingArgs {
fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<IbrokersPingArgs> {
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 = IbrokersPingArgs {};
Ok(ret)
}
fn write_to_out_protocol(&self, o_prot: &mut dyn 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()
}
}
//
// IbrokersPingResult
//
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct IbrokersPingResult {
result_value: Option<i32>,
error: Option<IBSAPIException>,
}
impl IbrokersPingResult {
fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<IbrokersPingResult> {
i_prot.read_struct_begin()?;
let mut f_0: Option<i32> = None;
let mut f_1: Option<IBSAPIException> = 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 = IBSAPIException::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 = IbrokersPingResult {
result_value: f_0,
error: f_1,
};
Ok(ret)
}
fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {
let struct_ident = TStructIdentifier::new("IbrokersPingResult");
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()?
}
if let Some(ref fld_var) = self.error {
o_prot.write_field_begin(&TFieldIdentifier::new("error", TType::Struct, 1))?;
fld_var.write_to_out_protocol(o_prot)?;
o_prot.write_field_end()?
}
o_prot.write_field_stop()?;
o_prot.write_struct_end()
}
fn ok_or(self) -> thrift::Result<i32> {
if self.error.is_some() {
Err(thrift::Error::User(Box::new(self.error.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 IbrokersPing"
)
)
)
}
}
}
//
// IbrokersIbStatusArgs
//
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct IbrokersIbStatusArgs {
}
impl IbrokersIbStatusArgs {
fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<IbrokersIbStatusArgs> {
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 = IbrokersIbStatusArgs {};
Ok(ret)
}
fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {
let struct_ident = TStructIdentifier::new("ib_status_args");
o_prot.write_struct_begin(&struct_ident)?;
o_prot.write_field_stop()?;
o_prot.write_struct_end()
}
}
//
// IbrokersIbStatusResult
//
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct IbrokersIbStatusResult {
result_value: Option<Vec<String>>,
error: Option<IBSAPIException>,
}
impl IbrokersIbStatusResult {
fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<IbrokersIbStatusResult> {
i_prot.read_struct_begin()?;
let mut f_0: Option<Vec<String>> = None;
let mut f_1: Option<IBSAPIException> = 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 list_ident = i_prot.read_list_begin()?;
let mut val: Vec<String> = Vec::with_capacity(list_ident.size as usize);
for _ in 0..list_ident.size {
let list_elem_0 = i_prot.read_string()?;
val.push(list_elem_0);
}
i_prot.read_list_end()?;
f_0 = Some(val);
},
1 => {
let val = IBSAPIException::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 = IbrokersIbStatusResult {
result_value: f_0,
error: f_1,
};
Ok(ret)
}
fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {
let struct_ident = TStructIdentifier::new("IbrokersIbStatusResult");
o_prot.write_struct_begin(&struct_ident)?;
if let Some(ref fld_var) = self.result_value {
o_prot.write_field_begin(&TFieldIdentifier::new("result_value", TType::List, 0))?;
o_prot.write_list_begin(&TListIdentifier::new(TType::String, fld_var.len() as i32))?;
for e in fld_var {
o_prot.write_string(e)?;
}
o_prot.write_list_end()?;
o_prot.write_field_end()?
}
if let Some(ref fld_var) = self.error {
o_prot.write_field_begin(&TFieldIdentifier::new("error", TType::Struct, 1))?;
fld_var.write_to_out_protocol(o_prot)?;
o_prot.write_field_end()?
}
o_prot.write_field_stop()?;
o_prot.write_struct_end()
}
fn ok_or(self) -> thrift::Result<Vec<String>> {
if self.error.is_some() {
Err(thrift::Error::User(Box::new(self.error.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 IbrokersIbStatus"
)
)
)
}
}
}
edit: went ahead and opened a ticket in Thrift [THRIFT-5664] fairly simple .thrift service call in rust , attempts to allocate too much memory and crashes - ASF JIRA