in thrift/compiler/generate/t_cocoa_generator.cc [1792:1981]
void t_cocoa_generator::generate_cocoa_service_client_implementation(
std::ofstream& out, const t_service* tservice) {
out << "@implementation " << cocoa_prefix_ << tservice->name() << "Client"
<< std::endl;
// initializers
out << "- (id) initWithProtocol: (id <TProtocol>) protocol" << std::endl;
scope_up(out);
out << indent()
<< "return [self initWithInProtocol: protocol outProtocol: protocol];"
<< std::endl;
scope_down(out);
out << std::endl;
out << "- (id) initWithInProtocol: (id <TProtocol>) anInProtocol outProtocol: (id <TProtocol>) anOutProtocol"
<< std::endl;
scope_up(out);
out << indent() << "self = [super init];" << std::endl;
out << indent() << "inProtocol = [anInProtocol retain_stub];" << std::endl;
out << indent() << "outProtocol = [anOutProtocol retain_stub];" << std::endl;
out << indent() << "return self;" << std::endl;
scope_down(out);
out << std::endl;
// dealloc
out << "- (void) dealloc" << std::endl;
scope_up(out);
out << indent() << "[inProtocol release_stub];" << std::endl;
out << indent() << "[outProtocol release_stub];" << std::endl;
out << indent() << "[super dealloc_stub];" << std::endl;
scope_down(out);
out << std::endl;
// generate client method implementations
for (const auto* function : tservice->get_functions()) {
const std::string& funname = function->name();
t_function send_function(
&t_base_type::t_void(),
std::string("send_") + function->name(),
t_struct::clone_DO_NOT_USE(function->get_paramlist()));
std::string argsname = function->name() + "_args";
// Open function
indent(out) << "- " << function_signature(&send_function) << std::endl;
scope_up(out);
// Serialize the request
out << indent() << "[outProtocol writeMessageBeginWithName: @\"" << funname
<< "\""
<< " type: TMessageType_CALL"
<< " sequenceID: 0];" << std::endl;
out << indent() << "[outProtocol writeStructBeginWithName: @\"" << argsname
<< "\"];" << std::endl;
// write out function parameters
for (const auto& param : function->get_paramlist()->fields()) {
const std::string& fieldName = param.name();
if (type_can_be_null(param.get_type())) {
out << indent() << "if (" << fieldName << " != nil)";
scope_up(out);
}
out << indent() << "[outProtocol writeFieldBeginWithName: @\""
<< fieldName
<< "\""
" type: "
<< type_to_enum(param.get_type()) << " fieldID: " << param.get_key()
<< "];" << std::endl;
generate_serialize_field(out, ¶m, fieldName);
out << indent() << "[outProtocol writeFieldEnd];" << std::endl;
if (type_can_be_null(param.get_type())) {
scope_down(out);
}
}
out << indent() << "[outProtocol writeFieldStop];" << std::endl;
out << indent() << "[outProtocol writeStructEnd];" << std::endl;
out << indent() << "[outProtocol writeMessageEnd];" << std::endl
<< indent() << "[[outProtocol transport] flush];" << std::endl;
scope_down(out);
out << std::endl;
if (function->qualifier() != t_function_qualifier::one_way) {
t_function recv_function(
function->get_returntype(),
std::string("recv_") + function->name(),
std::make_unique<t_paramlist>(program_),
t_struct::clone_DO_NOT_USE(function->get_xceptions()));
// Open function
indent(out) << "- " << function_signature(&recv_function) << std::endl;
scope_up(out);
// TODO(mcslee): Message validation here, was the seqid etc ok?
// check for an exception
out << indent() << "int msgType = 0;" << std::endl
<< indent()
<< "[inProtocol readMessageBeginReturningName: nil type: &msgType sequenceID: NULL];"
<< std::endl
<< indent() << "if (msgType == TMessageType_EXCEPTION) {" << std::endl
<< indent()
<< " TApplicationException * x = [TApplicationException read: inProtocol];"
<< std::endl
<< indent() << " [inProtocol readMessageEnd];" << std::endl
<< indent() << " @throw x;" << std::endl
<< indent() << "}" << std::endl;
// FIXME - could optimize here to reduce creation of temporary objects.
std::string resultname = function_result_helper_struct_type(function);
out << indent() << cocoa_prefix_ << resultname << " * result = [[["
<< cocoa_prefix_ << resultname << " alloc] init] autorelease_stub];"
<< std::endl;
indent(out) << "[result read: inProtocol];" << std::endl;
indent(out) << "[inProtocol readMessageEnd];" << std::endl;
// Careful, only return _result if not a void function
if (!function->get_returntype()->is_void()) {
out << indent() << "if ([result successIsSet]) {" << std::endl
<< indent() << " return [result success];" << std::endl
<< indent() << "}" << std::endl;
}
if (function->exceptions() != nullptr) {
for (const auto& x : function->exceptions()->fields()) {
out << indent() << "if ([result " << x.name() << "IsSet]) {"
<< std::endl
<< indent() << " @throw [result " << x.name() << "];"
<< std::endl
<< indent() << "}" << std::endl;
}
}
// If you get here it's an exception, unless a void function
if (function->get_returntype()->is_void()) {
indent(out) << "return;" << std::endl;
} else {
out << indent()
<< "@throw [TApplicationException exceptionWithType: TApplicationException_MISSING_RESULT"
<< std::endl
<< indent()
<< " reason: @\""
<< function->name() << " failed: unknown result\"];" << std::endl;
}
// Close function
scope_down(out);
out << std::endl;
}
// Open function
indent(out) << "- " << function_signature(function) << std::endl;
scope_up(out);
indent(out) << "[self send_" << funname;
// Declare the function arguments
bool first = true;
for (const auto& param : function->get_paramlist()->fields()) {
const std::string& fieldName = param.name();
out << " ";
if (first) {
first = false;
out << ": " << fieldName;
} else {
out << fieldName << ": " << fieldName;
}
}
out << "];" << std::endl;
if (function->qualifier() != t_function_qualifier::one_way) {
out << indent();
if (!function->get_returntype()->is_void()) {
out << "return ";
}
out << "[self recv_" << funname << "];" << std::endl;
}
scope_down(out);
out << std::endl;
}
indent_down();
out << "@end" << std::endl << std::endl;
}