void t_swift_generator::generate_swift_service_server_implementation()

in compiler/cpp/src/thrift/generate/t_swift_generator.cc [2339:2524]


void t_swift_generator::generate_swift_service_server_implementation(ostream& out,
                                                                     t_service* tservice) {

  string name = tservice->get_name() + "Processor";

  indent(out) << "extension " << name << " : TProcessor";
  block_open(out);
  out << '\n';
  indent(out) << "static let processorHandlers" << (gen_cocoa_ ? " " : "") << ": ProcessorHandlerDictionary =";
  block_open(out);

  out << '\n';
  out << indent() << "var processorHandlers = ProcessorHandlerDictionary()" << '\n' << '\n';

  // generate method map for routing incoming calls
  vector<t_function*> functions = tservice->get_functions();
  vector<t_function*>::const_iterator f_iter;
  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {

    t_function* tfunction = *f_iter;

    string args_type = function_args_helper_struct_type(tservice, *f_iter);

    out << indent() << "processorHandlers[\"" << tfunction->get_name() << "\"] = { sequenceID, inProtocol, outProtocol, handler in" << '\n'
        << '\n';

    indent_up();
    if (!gen_cocoa_) {
      out << indent() << "let args = try " << args_type << ".read(from: inProtocol)" << '\n'
          << '\n'
          << indent() << "try inProtocol.readMessageEnd()" << '\n'
          << '\n';
    } else {
      out << indent() << "let args = try " << args_type << ".readValueFromProtocol(inProtocol)" << '\n'
          << '\n'
          << indent() << "try inProtocol.readMessageEnd()" << '\n'
          << '\n';
    }

    if (!tfunction->is_oneway() ) {
      string result_type = function_result_helper_struct_type(tservice, tfunction);
      indent(out) << "var result = " << result_type << "()" << '\n';

      indent(out) << "do";
      block_open(out);

      indent(out);
      if (!tfunction->get_returntype()->is_void()) {
        out << "result.success = ";
      }
      out << "try handler." << (gen_cocoa_ ? function_name(tfunction) : tfunction->get_name()) << "(";

      t_struct* arg_struct = tfunction->get_arglist();
      const vector<t_field*>& fields = arg_struct->get_members();
      vector<t_field*>::const_iterator f_iter;

      for (f_iter = fields.begin(); f_iter != fields.end();) {
        string fieldName = (*f_iter)->get_name();
        if (!gen_cocoa_ || f_iter != fields.begin()) {
          out << fieldName << ": ";
        }

        out << "args." << fieldName;
        if (++f_iter != fields.end()) {
          out << ", ";
        }
      }

      out << ")" << '\n';
      block_close(out);

      t_struct* xs = tfunction->get_xceptions();
      const vector<t_field*>& xfields = xs->get_members();
      vector<t_field*>::const_iterator x_iter;

      if (!gen_cocoa_) {
        for (x_iter = xfields.begin(); x_iter != xfields.end(); ++x_iter) {
          indent(out) << "catch let error as ";

          t_program* program = (*x_iter)->get_type()->get_program();
          if ((*x_iter)->get_type()->get_name() == "Error" && namespaced_ && program != program_) {
            out << get_real_swift_module(program) << ".";
          }
          out << (*x_iter)->get_type()->get_name();

          out << " { result." << (*x_iter)->get_name() << " = error }" << '\n';
        }

        indent(out) << "catch let error { throw error }" << '\n';
        out << '\n';

        if (!tfunction->is_oneway()) {
          out << indent() << "try outProtocol.writeMessageBegin(name: \"" << tfunction->get_name() << "\", type: .reply, sequenceID: sequenceID)" << '\n'
              << indent() << "try result.write(to: outProtocol)" << '\n'
              << indent() << "try outProtocol.writeMessageEnd()" << '\n'
              << indent() << "try outProtocol.transport.flush()" << '\n';
        }
      } else {
        for (x_iter = xfields.begin(); x_iter != xfields.end(); ++x_iter) {
          indent(out) << "catch let error as " << (*x_iter)->get_type()->get_name();
          block_open(out);
          indent(out) << "result." << (*x_iter)->get_name() << " = error" << '\n';
          block_close(out);
        }

        indent(out) << "catch let error";
        block_open(out);
        out << indent() << "throw error" << '\n';
        block_close(out);

        out << '\n';

        if (!tfunction->is_oneway()) {
          out << indent() << "try outProtocol.writeMessageBeginWithName(\"" << tfunction->get_name() << "\", type: .REPLY, sequenceID: sequenceID)" << '\n'
              << indent() << "try " << result_type << ".writeValue(result, toProtocol: outProtocol)" << '\n'
              << indent() << "try outProtocol.writeMessageEnd()" << '\n';
        }
      }
    }
    block_close(out);

  }

  indent(out) << "return processorHandlers" << '\n';

  block_close(out,false);
  out << "()" << '\n';
  out << '\n';

  if (!gen_cocoa_) {
    indent(out) << "public func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws";
  } else {
    indent(out) << "public func processOnInputProtocol(inProtocol: TProtocol, outputProtocol outProtocol: TProtocol) throws";
  }
  block_open(out);

  out << '\n';
  out << indent() << "let (messageName, _, sequenceID) = try inProtocol.readMessageBegin()" << '\n'
      << '\n'
      << indent() << "if let processorHandler = " << name << ".processorHandlers[messageName]";
  block_open(out);
  out << indent() << "do";
  block_open(out);
  out << indent() << "try processorHandler(sequenceID, inProtocol, outProtocol, service)" << '\n';
  block_close(out);
  if (!gen_cocoa_) {
    out << indent() << "catch let error as TApplicationError";
    block_open(out);
    out << indent() << "try outProtocol.writeException(messageName: messageName, sequenceID: sequenceID, ex: error)" << '\n'
        << indent() << "try outProtocol.transport.flush()" << '\n';
    block_close(out);
    block_close(out);
    out << indent() << "else";
    block_open(out);
    out << indent() << "try inProtocol.skip(type: .struct)" << '\n'
        << indent() << "try inProtocol.readMessageEnd()" << '\n'
        << indent() << "let ex = TApplicationError(error: .unknownMethod(methodName: messageName))" << '\n'
        << indent() << "try outProtocol.writeException(messageName: messageName, sequenceID: sequenceID, ex: ex)" << '\n'
        << indent() << "try outProtocol.transport.flush()" << '\n';
  } else {
    out << indent() << "catch let error as NSError";
    block_open(out);
    out << indent() << "try outProtocol.writeExceptionForMessageName(messageName, sequenceID: sequenceID, ex: error)" << '\n';
    block_close(out);
    block_close(out);
    out << indent() << "else";
    block_open(out);
    out << indent() << "try inProtocol.skipType(.STRUCT)" << '\n'
        << indent() << "try inProtocol.readMessageEnd()" << '\n'
        << indent() << "try outProtocol.writeExceptionForMessageName(messageName," << '\n';
    indent_up();
    out << indent() << "sequenceID: sequenceID," << '\n'
        << indent() << "ex: NSError(" << '\n';
    indent_up();
    out << indent() << "domain: TApplicationErrorDomain, " << '\n'
        << indent() << "code: Int(TApplicationError.UnknownMethod.rawValue), " << '\n'
        << indent() << "userInfo: [TApplicationErrorMethodKey: messageName]))" << '\n';
    indent_down();
    indent_down();
  }

  block_close(out);
  block_close(out);
  block_close(out);
  out << '\n';
}