in thrift/compiler/generate/t_hack_generator.cc [5756:5955]
void t_hack_generator::_generate_recvImpl(
std::ofstream& out,
const t_service* tservice,
const t_function* tfunction) {
auto ttype = tfunction->get_returntype();
std::string return_typehint;
std::string resultname;
std::string recvImpl_method_name;
bool is_void = false;
if (const auto* tstream = dynamic_cast<const t_stream_response*>(ttype)) {
_generate_stream_decode_recvImpl(out, tservice, tfunction);
resultname = generate_function_helper_name(
tservice, tfunction, PhpFunctionNameSuffix::FIRST_RESPONSE);
recvImpl_method_name =
std::string("recvImpl_") + tfunction->name() + "_FirstResponse";
if (tstream->has_first_response()) {
ttype = tstream->get_first_response_type();
return_typehint = type_to_typehint(ttype);
} else {
return_typehint = "void";
is_void = true;
}
} else if (const auto* tsink = dynamic_cast<const t_sink*>(ttype)) {
_generate_sink_final_response_decode_recvImpl(out, tservice, tfunction);
resultname = generate_function_helper_name(
tservice, tfunction, PhpFunctionNameSuffix::FIRST_RESPONSE);
recvImpl_method_name =
std::string("recvImpl_") + tfunction->name() + "_FirstResponse";
if (tsink->sink_has_first_response()) {
ttype = tsink->get_first_response_type();
return_typehint = type_to_typehint(ttype);
} else {
return_typehint = "void";
is_void = true;
}
} else {
resultname = generate_function_helper_name(
tservice, tfunction, PhpFunctionNameSuffix::RESULT);
recvImpl_method_name = std::string("recvImpl_") + tfunction->name();
return_typehint = type_to_typehint(ttype);
is_void = ttype->is_void();
}
const std::string& rpc_function_name =
generate_rpc_function_name(tservice, tfunction);
t_function recv_function(
tfunction->get_returntype(),
recvImpl_method_name,
std::make_unique<t_paramlist>(program_));
// Open function
out << "\n";
out << indent() << "protected function "
<< function_signature(
&recv_function,
"?int $expectedsequenceid = null"
", shape(?'read_options' => int) $options = shape()",
return_typehint)
<< " {\n";
indent_up();
out << indent() << "try {\n";
indent_up();
out << indent() << "$this->eventHandler_->preRecv('" << rpc_function_name
<< "', $expectedsequenceid);\n";
out << indent() << "if ($this->input_ is \\TBinaryProtocolAccelerated) {\n";
indent_up();
out << indent() << "$result = \\thrift_protocol_read_binary("
<< "$this->input_"
<< ", '" << resultname << "'"
<< ", $this->input_->isStrictRead()"
<< ", Shapes::idx($options, 'read_options', 0)"
<< ");\n";
indent_down();
out << indent()
<< "} else if ($this->input_ is \\TCompactProtocolAccelerated)\n";
scope_up(out);
out << indent() << "$result = \\thrift_protocol_read_compact("
<< "$this->input_"
<< ", '" << resultname << "'"
<< ", Shapes::idx($options, 'read_options', 0)"
<< ");\n";
scope_down(out);
out << indent() << "else\n";
scope_up(out);
out << indent() << "$rseqid = 0;\n"
<< indent() << "$fname = '';\n"
<< indent() << "$mtype = 0;\n\n";
out << indent() << "$this->input_->readMessageBegin(\n"
<< indent() << " inout $fname,\n"
<< indent() << " inout $mtype,\n"
<< indent() << " inout $rseqid,\n"
<< indent() << ");\n"
<< indent() << "if ($mtype === \\TMessageType::EXCEPTION) {\n"
<< indent() << " $x = new \\TApplicationException();\n"
<< indent() << " $x->read($this->input_);\n"
<< indent() << " $this->input_->readMessageEnd();\n"
<< indent() << " throw $x;\n"
<< indent() << "}\n";
out << indent() << "$result = " << resultname << "::withDefaultValues();\n"
<< indent() << "$result->read($this->input_);\n";
out << indent() << "$this->input_->readMessageEnd();\n";
out << indent()
<< "if ($expectedsequenceid !== null && ($rseqid !== $expectedsequenceid)) {\n"
<< indent() << " throw new \\TProtocolException(\"" << tfunction->name()
<< " failed: sequence id is out of order\");\n"
<< indent() << "}\n";
scope_down(out);
indent_down();
indent(out) << "} catch (\\THandlerShortCircuitException $ex) {\n";
indent_up();
out << indent() << "switch ($ex->resultType) {\n"
<< indent() << " case \\THandlerShortCircuitException::R_EXPECTED_EX:\n"
<< indent() << " $this->eventHandler_->recvException('"
<< rpc_function_name << "', $expectedsequenceid, $ex->result);\n"
<< indent() << " throw $ex->result;\n"
<< indent()
<< " case \\THandlerShortCircuitException::R_UNEXPECTED_EX:\n"
<< indent() << " $this->eventHandler_->recvError('"
<< rpc_function_name << "', $expectedsequenceid, $ex->result);\n"
<< indent() << " throw $ex->result;\n"
<< indent() << " case \\THandlerShortCircuitException::R_SUCCESS:\n"
<< indent() << " default:\n"
<< indent() << " $this->eventHandler_->postRecv('" << rpc_function_name
<< "', $expectedsequenceid, $ex->result);\n"
<< indent() << " return";
if (!is_void) {
out << " $ex->result";
}
out << ";\n" << indent() << "}\n";
indent_down();
out << indent() << "} catch (\\Exception $ex) {\n";
indent_up();
out << indent() << "$this->eventHandler_->recvError('" << rpc_function_name
<< "', $expectedsequenceid, $ex);\n"
<< indent() << "throw $ex;\n";
indent_down();
out << indent() << "}\n";
// Careful, only return result if not a void function
if (!is_void) {
out << indent() << "if ($result->success !== null) {\n"
<< indent() << " $success = $result->success;\n"
<< indent() << " $this->eventHandler_->postRecv('" << rpc_function_name
<< "', $expectedsequenceid, $success);"
<< "\n"
<< indent() << " return $success;\n"
<< indent() << "}\n";
}
for (const auto& x : tfunction->get_xceptions()->fields()) {
out << indent() << "if ($result->" << x.name() << " !== null) {\n"
<< indent() << " $x = $result->" << x.name() << ";"
<< "\n"
<< indent() << " $this->eventHandler_->recvException('"
<< rpc_function_name << "', $expectedsequenceid, $x);\n"
<< indent() << " throw $x;\n"
<< indent() << "}\n";
}
// Careful, only return _result if not a void function
if (is_void) {
out << indent() << "$this->eventHandler_->postRecv('" << rpc_function_name
<< "', $expectedsequenceid, null);\n"
<< indent() << "return;\n";
} else {
out << indent() << "$x = new \\TApplicationException(\""
<< tfunction->name() << " failed: unknown result\""
<< ", \\TApplicationException::MISSING_RESULT"
<< ");\n"
<< indent() << "$this->eventHandler_->recvError('" << rpc_function_name
<< "', $expectedsequenceid, $x);\n"
<< indent() << "throw $x;\n";
}
// Close function
scope_down(out);
}