Squashed 'third_party/flatbuffers/' content from commit acc9990ab

Change-Id: I48550d40d78fea996ebe74e9723a5d1f910de491
git-subtree-dir: third_party/flatbuffers
git-subtree-split: acc9990abd2206491480291b0f85f925110102ea
diff --git a/grpc/src/compiler/cpp_generator.cc b/grpc/src/compiler/cpp_generator.cc
new file mode 100644
index 0000000..6cfd22e
--- /dev/null
+++ b/grpc/src/compiler/cpp_generator.cc
@@ -0,0 +1,1780 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <map>
+
+#include "src/compiler/cpp_generator.h"
+#include "flatbuffers/util.h"
+
+#include <sstream>
+
+namespace grpc_cpp_generator {
+namespace {
+
+grpc::string message_header_ext() { return "_generated.h"; }
+grpc::string service_header_ext() { return ".grpc.fb.h"; }
+
+template <class T>
+grpc::string as_string(T x) {
+  std::ostringstream out;
+  out << x;
+  return out.str();
+}
+
+inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
+  return method->ClientStreaming() && !method->ServerStreaming();
+}
+
+inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
+  return !method->ClientStreaming() && method->ServerStreaming();
+}
+
+grpc::string FilenameIdentifier(const grpc::string &filename) {
+  grpc::string result;
+  for (unsigned i = 0; i < filename.size(); i++) {
+    char c = filename[i];
+    if (isalnum(c)) {
+      result.push_back(c);
+    } else {
+      static char hex[] = "0123456789abcdef";
+      result.push_back('_');
+      result.push_back(hex[(c >> 4) & 0xf]);
+      result.push_back(hex[c & 0xf]);
+    }
+  }
+  return result;
+}
+}  // namespace
+
+template <class T, size_t N>
+T *array_end(T (&array)[N]) {
+  return array + N;
+}
+
+void PrintIncludes(grpc_generator::Printer *printer,
+                   const std::vector<grpc::string> &headers,
+                   const Parameters &params) {
+  std::map<grpc::string, grpc::string> vars;
+
+  vars["l"] = params.use_system_headers ? '<' : '"';
+  vars["r"] = params.use_system_headers ? '>' : '"';
+
+  auto &s = params.grpc_search_path;
+  if (!s.empty()) {
+    vars["l"] += s;
+    if (s[s.size() - 1] != '/') {
+      vars["l"] += '/';
+    }
+  }
+
+  for (auto i = headers.begin(); i != headers.end(); i++) {
+    vars["h"] = *i;
+    printer->Print(vars, "#include $l$$h$$r$\n");
+  }
+}
+
+grpc::string GetHeaderPrologue(grpc_generator::File *file,
+                               const Parameters & /*params*/) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+
+    vars["filename"] = file->filename();
+    vars["filename_identifier"] = FilenameIdentifier(file->filename());
+    vars["filename_base"] = file->filename_without_ext();
+    vars["message_header_ext"] = message_header_ext();
+
+    printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
+    printer->Print(vars,
+                   "// If you make any local change, they will be lost.\n");
+    printer->Print(vars, "// source: $filename$\n");
+    grpc::string leading_comments = file->GetLeadingComments("//");
+    if (!leading_comments.empty()) {
+      printer->Print(vars, "// Original file comments:\n");
+      printer->Print(leading_comments.c_str());
+    }
+    printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
+    printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
+    printer->Print(vars, "\n");
+    printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
+    printer->Print(vars, file->additional_headers().c_str());
+    printer->Print(vars, "\n");
+  }
+  return output;
+}
+
+grpc::string GetHeaderIncludes(grpc_generator::File *file,
+                               const Parameters &params) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+
+    static const char *headers_strs[] = {
+        "grpc++/impl/codegen/async_stream.h",
+        "grpc++/impl/codegen/async_unary_call.h",
+        "grpc++/impl/codegen/method_handler_impl.h",
+        "grpc++/impl/codegen/proto_utils.h",
+        "grpc++/impl/codegen/rpc_method.h",
+        "grpc++/impl/codegen/service_type.h",
+        "grpc++/impl/codegen/status.h",
+        "grpc++/impl/codegen/stub_options.h",
+        "grpc++/impl/codegen/sync_stream.h"};
+    std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
+    PrintIncludes(printer.get(), headers, params);
+    printer->Print(vars, "\n");
+    printer->Print(vars, "namespace grpc {\n");
+    printer->Print(vars, "class CompletionQueue;\n");
+    printer->Print(vars, "class Channel;\n");
+    printer->Print(vars, "class ServerCompletionQueue;\n");
+    printer->Print(vars, "class ServerContext;\n");
+    printer->Print(vars, "}  // namespace grpc\n\n");
+
+    if (!file->package().empty()) {
+      std::vector<grpc::string> parts = file->package_parts();
+
+      for (auto part = parts.begin(); part != parts.end(); part++) {
+        vars["part"] = *part;
+        printer->Print(vars, "namespace $part$ {\n");
+      }
+      printer->Print(vars, "\n");
+    }
+  }
+  return output;
+}
+
+void PrintHeaderClientMethodInterfaces(
+    grpc_generator::Printer *printer, const grpc_generator::Method *method,
+    std::map<grpc::string, grpc::string> *vars, bool is_public) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+
+  struct {
+    grpc::string prefix;
+    grpc::string method_params;  // extra arguments to method
+    grpc::string raw_args;       // extra arguments to raw version of method
+  } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
+                        {"PrepareAsync", "", ""}};
+
+  if (is_public) {
+    if (method->NoStreaming()) {
+      printer->Print(
+          *vars,
+          "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
+          "const $Request$& request, $Response$* response) = 0;\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        printer->Print(
+            *vars,
+            "std::unique_ptr< "
+            "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
+            "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+            "const $Request$& request, "
+            "::grpc::CompletionQueue* cq) {\n");
+        printer->Indent();
+        printer->Print(
+            *vars,
+            "return std::unique_ptr< "
+            "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
+            "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    } else if (ClientOnlyStreaming(method)) {
+      printer->Print(
+          *vars,
+          "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
+          " $Method$("
+          "::grpc::ClientContext* context, $Response$* response) {\n");
+      printer->Indent();
+      printer->Print(
+          *vars,
+          "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
+          "($Method$Raw(context, response));\n");
+      printer->Outdent();
+      printer->Print("}\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+        printer->Print(
+            *vars,
+            "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
+            " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+            "$Response$* "
+            "response, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+        printer->Indent();
+        printer->Print(*vars,
+                       "return std::unique_ptr< "
+                       "::grpc::ClientAsyncWriterInterface< $Request$>>("
+                       "$AsyncPrefix$$Method$Raw(context, response, "
+                       "cq$AsyncRawArgs$));\n");
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    } else if (ServerOnlyStreaming(method)) {
+      printer->Print(
+          *vars,
+          "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
+          " $Method$(::grpc::ClientContext* context, const $Request$& request)"
+          " {\n");
+      printer->Indent();
+      printer->Print(
+          *vars,
+          "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
+          "($Method$Raw(context, request));\n");
+      printer->Outdent();
+      printer->Print("}\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+        printer->Print(
+            *vars,
+            "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
+            "$AsyncPrefix$$Method$("
+            "::grpc::ClientContext* context, const $Request$& request, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+        printer->Indent();
+        printer->Print(
+            *vars,
+            "return std::unique_ptr< "
+            "::grpc::ClientAsyncReaderInterface< $Response$>>("
+            "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    } else if (method->BidiStreaming()) {
+      printer->Print(*vars,
+                     "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
+                     "$Request$, $Response$>> "
+                     "$Method$(::grpc::ClientContext* context) {\n");
+      printer->Indent();
+      printer->Print(
+          *vars,
+          "return std::unique_ptr< "
+          "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
+          "$Method$Raw(context));\n");
+      printer->Outdent();
+      printer->Print("}\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+        printer->Print(
+            *vars,
+            "std::unique_ptr< "
+            "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
+            "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+        printer->Indent();
+        printer->Print(
+            *vars,
+            "return std::unique_ptr< "
+            "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
+            "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    }
+  } else {
+    if (method->NoStreaming()) {
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        printer->Print(
+            *vars,
+            "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
+            "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+            "const $Request$& request, "
+            "::grpc::CompletionQueue* cq) = 0;\n");
+      }
+    } else if (ClientOnlyStreaming(method)) {
+      printer->Print(
+          *vars,
+          "virtual ::grpc::ClientWriterInterface< $Request$>*"
+          " $Method$Raw("
+          "::grpc::ClientContext* context, $Response$* response) = 0;\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        printer->Print(
+            *vars,
+            "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
+            " $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+            "$Response$* response, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
+      }
+    } else if (ServerOnlyStreaming(method)) {
+      printer->Print(
+          *vars,
+          "virtual ::grpc::ClientReaderInterface< $Response$>* "
+          "$Method$Raw("
+          "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        printer->Print(
+            *vars,
+            "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
+            "$AsyncPrefix$$Method$Raw("
+            "::grpc::ClientContext* context, const $Request$& request, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
+      }
+    } else if (method->BidiStreaming()) {
+      printer->Print(*vars,
+                     "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
+                     "$Response$>* "
+                     "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        printer->Print(
+            *vars,
+            "virtual ::grpc::ClientAsyncReaderWriterInterface< "
+            "$Request$, $Response$>* "
+            "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
+      }
+    }
+  }
+}
+
+void PrintHeaderClientMethod(grpc_generator::Printer *printer,
+                             const grpc_generator::Method *method,
+                             std::map<grpc::string, grpc::string> *vars,
+                             bool is_public) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  struct {
+    grpc::string prefix;
+    grpc::string method_params;  // extra arguments to method
+    grpc::string raw_args;       // extra arguments to raw version of method
+  } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
+                        {"PrepareAsync", "", ""}};
+
+  if (is_public) {
+    if (method->NoStreaming()) {
+      printer->Print(
+          *vars,
+          "::grpc::Status $Method$(::grpc::ClientContext* context, "
+          "const $Request$& request, $Response$* response) override;\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        printer->Print(
+            *vars,
+            "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
+            "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+            "const $Request$& request, "
+            "::grpc::CompletionQueue* cq) {\n");
+        printer->Indent();
+        printer->Print(*vars,
+                       "return std::unique_ptr< "
+                       "::grpc::ClientAsyncResponseReader< $Response$>>("
+                       "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    } else if (ClientOnlyStreaming(method)) {
+      printer->Print(
+          *vars,
+          "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
+          " $Method$("
+          "::grpc::ClientContext* context, $Response$* response) {\n");
+      printer->Indent();
+      printer->Print(*vars,
+                     "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
+                     "($Method$Raw(context, response));\n");
+      printer->Outdent();
+      printer->Print("}\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+        printer->Print(*vars,
+                       "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
+                       " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+                       "$Response$* response, "
+                       "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+        printer->Indent();
+        printer->Print(
+            *vars,
+            "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
+            "$AsyncPrefix$$Method$Raw(context, response, "
+            "cq$AsyncRawArgs$));\n");
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    } else if (ServerOnlyStreaming(method)) {
+      printer->Print(
+          *vars,
+          "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
+          " $Method$(::grpc::ClientContext* context, const $Request$& request)"
+          " {\n");
+      printer->Indent();
+      printer->Print(
+          *vars,
+          "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
+          "($Method$Raw(context, request));\n");
+      printer->Outdent();
+      printer->Print("}\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+        printer->Print(
+            *vars,
+            "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
+            "$AsyncPrefix$$Method$("
+            "::grpc::ClientContext* context, const $Request$& request, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+        printer->Indent();
+        printer->Print(
+            *vars,
+            "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
+            "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    } else if (method->BidiStreaming()) {
+      printer->Print(
+          *vars,
+          "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
+          " $Method$(::grpc::ClientContext* context) {\n");
+      printer->Indent();
+      printer->Print(*vars,
+                     "return std::unique_ptr< "
+                     "::grpc::ClientReaderWriter< $Request$, $Response$>>("
+                     "$Method$Raw(context));\n");
+      printer->Outdent();
+      printer->Print("}\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+        printer->Print(*vars,
+                       "std::unique_ptr<  ::grpc::ClientAsyncReaderWriter< "
+                       "$Request$, $Response$>> "
+                       "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+                       "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+        printer->Indent();
+        printer->Print(
+            *vars,
+            "return std::unique_ptr< "
+            "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
+            "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    }
+  } else {
+    if (method->NoStreaming()) {
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        printer->Print(
+            *vars,
+            "::grpc::ClientAsyncResponseReader< $Response$>* "
+            "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+            "const $Request$& request, "
+            "::grpc::CompletionQueue* cq) override;\n");
+      }
+    } else if (ClientOnlyStreaming(method)) {
+      printer->Print(*vars,
+                     "::grpc::ClientWriter< $Request$>* $Method$Raw("
+                     "::grpc::ClientContext* context, $Response$* response) "
+                     "override;\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+        printer->Print(
+            *vars,
+            "::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
+            "::grpc::ClientContext* context, $Response$* response, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
+      }
+    } else if (ServerOnlyStreaming(method)) {
+      printer->Print(*vars,
+                     "::grpc::ClientReader< $Response$>* $Method$Raw("
+                     "::grpc::ClientContext* context, const $Request$& request)"
+                     " override;\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+        printer->Print(
+            *vars,
+            "::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
+            "::grpc::ClientContext* context, const $Request$& request, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
+      }
+    } else if (method->BidiStreaming()) {
+      printer->Print(*vars,
+                     "::grpc::ClientReaderWriter< $Request$, $Response$>* "
+                     "$Method$Raw(::grpc::ClientContext* context) override;\n");
+      for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+        auto& async_prefix = async_prefixes[i];
+        (*vars)["AsyncPrefix"] = async_prefix.prefix;
+        (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+        (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+        printer->Print(
+            *vars,
+            "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
+            "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+            "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
+      }
+    }
+  }
+}
+
+void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
+                                 const grpc_generator::Method *method,
+                                 std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Method"] = method->name();
+  printer->Print(*vars,
+                 "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
+}
+
+void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
+                                 const grpc_generator::Method *method,
+                                 std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  printer->Print(method->GetLeadingComments("//").c_str());
+  if (method->NoStreaming()) {
+    printer->Print(*vars,
+                   "virtual ::grpc::Status $Method$("
+                   "::grpc::ServerContext* context, const $Request$* request, "
+                   "$Response$* response);\n");
+  } else if (ClientOnlyStreaming(method)) {
+    printer->Print(*vars,
+                   "virtual ::grpc::Status $Method$("
+                   "::grpc::ServerContext* context, "
+                   "::grpc::ServerReader< $Request$>* reader, "
+                   "$Response$* response);\n");
+  } else if (ServerOnlyStreaming(method)) {
+    printer->Print(*vars,
+                   "virtual ::grpc::Status $Method$("
+                   "::grpc::ServerContext* context, const $Request$* request, "
+                   "::grpc::ServerWriter< $Response$>* writer);\n");
+  } else if (method->BidiStreaming()) {
+    printer->Print(
+        *vars,
+        "virtual ::grpc::Status $Method$("
+        "::grpc::ServerContext* context, "
+        "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
+        "\n");
+  }
+  printer->Print(method->GetTrailingComments("//").c_str());
+}
+
+void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
+                                  const grpc_generator::Method *method,
+                                  std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  printer->Print(*vars, "template <class BaseClass>\n");
+  printer->Print(*vars,
+                 "class WithAsyncMethod_$Method$ : public BaseClass {\n");
+  printer->Print(
+      " private:\n"
+      "  void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
+  printer->Print(" public:\n");
+  printer->Indent();
+  printer->Print(*vars,
+                 "WithAsyncMethod_$Method$() {\n"
+                 "  ::grpc::Service::MarkMethodAsync($Idx$);\n"
+                 "}\n");
+  printer->Print(*vars,
+                 "~WithAsyncMethod_$Method$() override {\n"
+                 "  BaseClassMustBeDerivedFromService(this);\n"
+                 "}\n");
+  if (method->NoStreaming()) {
+    printer->Print(
+        *vars,
+        "// disable synchronous version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, const $Request$* request, "
+        "$Response$* response) final override {\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+    printer->Print(
+        *vars,
+        "void Request$Method$("
+        "::grpc::ServerContext* context, $Request$* request, "
+        "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
+        "::grpc::CompletionQueue* new_call_cq, "
+        "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
+    printer->Print(*vars,
+                   "  ::grpc::Service::RequestAsyncUnary($Idx$, context, "
+                   "request, response, new_call_cq, notification_cq, tag);\n");
+    printer->Print("}\n");
+  } else if (ClientOnlyStreaming(method)) {
+    printer->Print(
+        *vars,
+        "// disable synchronous version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, "
+        "::grpc::ServerReader< $Request$>* reader, "
+        "$Response$* response) final override {\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+    printer->Print(
+        *vars,
+        "void Request$Method$("
+        "::grpc::ServerContext* context, "
+        "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
+        "::grpc::CompletionQueue* new_call_cq, "
+        "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
+    printer->Print(*vars,
+                   "  ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
+                   "context, reader, new_call_cq, notification_cq, tag);\n");
+    printer->Print("}\n");
+  } else if (ServerOnlyStreaming(method)) {
+    printer->Print(
+        *vars,
+        "// disable synchronous version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, const $Request$* request, "
+        "::grpc::ServerWriter< $Response$>* writer) final override "
+        "{\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+    printer->Print(
+        *vars,
+        "void Request$Method$("
+        "::grpc::ServerContext* context, $Request$* request, "
+        "::grpc::ServerAsyncWriter< $Response$>* writer, "
+        "::grpc::CompletionQueue* new_call_cq, "
+        "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
+    printer->Print(
+        *vars,
+        "  ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
+        "context, request, writer, new_call_cq, notification_cq, tag);\n");
+    printer->Print("}\n");
+  } else if (method->BidiStreaming()) {
+    printer->Print(
+        *vars,
+        "// disable synchronous version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, "
+        "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
+        "final override {\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+    printer->Print(
+        *vars,
+        "void Request$Method$("
+        "::grpc::ServerContext* context, "
+        "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
+        "::grpc::CompletionQueue* new_call_cq, "
+        "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
+    printer->Print(*vars,
+                   "  ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
+                   "context, stream, new_call_cq, notification_cq, tag);\n");
+    printer->Print("}\n");
+  }
+  printer->Outdent();
+  printer->Print(*vars, "};\n");
+}
+
+void PrintHeaderServerMethodStreamedUnary(
+    grpc_generator::Printer *printer, const grpc_generator::Method *method,
+    std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  if (method->NoStreaming()) {
+    printer->Print(*vars, "template <class BaseClass>\n");
+    printer->Print(*vars,
+                   "class WithStreamedUnaryMethod_$Method$ : "
+                   "public BaseClass {\n");
+    printer->Print(
+        " private:\n"
+        "  void BaseClassMustBeDerivedFromService(const Service *service) "
+        "{}\n");
+    printer->Print(" public:\n");
+    printer->Indent();
+    printer->Print(*vars,
+                   "WithStreamedUnaryMethod_$Method$() {\n"
+                   "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
+                   "    new ::grpc::internal::StreamedUnaryHandler< $Request$, "
+                   "$Response$>(std::bind"
+                   "(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
+                   "Streamed$Method$, this, std::placeholders::_1, "
+                   "std::placeholders::_2)));\n"
+                   "}\n");
+    printer->Print(*vars,
+                   "~WithStreamedUnaryMethod_$Method$() override {\n"
+                   "  BaseClassMustBeDerivedFromService(this);\n"
+                   "}\n");
+    printer->Print(
+        *vars,
+        "// disable regular version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, const $Request$* request, "
+        "$Response$* response) final override {\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+    printer->Print(*vars,
+                   "// replace default version of method with streamed unary\n"
+                   "virtual ::grpc::Status Streamed$Method$("
+                   "::grpc::ServerContext* context, "
+                   "::grpc::ServerUnaryStreamer< "
+                   "$Request$,$Response$>* server_unary_streamer)"
+                   " = 0;\n");
+    printer->Outdent();
+    printer->Print(*vars, "};\n");
+  }
+}
+
+void PrintHeaderServerMethodSplitStreaming(
+    grpc_generator::Printer *printer, const grpc_generator::Method *method,
+    std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  if (ServerOnlyStreaming(method)) {
+    printer->Print(*vars, "template <class BaseClass>\n");
+    printer->Print(*vars,
+                   "class WithSplitStreamingMethod_$Method$ : "
+                   "public BaseClass {\n");
+    printer->Print(
+        " private:\n"
+        "  void BaseClassMustBeDerivedFromService(const Service *service) "
+        "{}\n");
+    printer->Print(" public:\n");
+    printer->Indent();
+    printer->Print(
+        *vars,
+        "WithSplitStreamingMethod_$Method$() {\n"
+        "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
+        "    new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
+        "$Response$>(std::bind"
+        "(&WithSplitStreamingMethod_$Method$<BaseClass>::"
+        "Streamed$Method$, this, std::placeholders::_1, "
+        "std::placeholders::_2)));\n"
+        "}\n");
+    printer->Print(*vars,
+                   "~WithSplitStreamingMethod_$Method$() override {\n"
+                   "  BaseClassMustBeDerivedFromService(this);\n"
+                   "}\n");
+    printer->Print(
+        *vars,
+        "// disable regular version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, const $Request$* request, "
+        "::grpc::ServerWriter< $Response$>* writer) final override "
+        "{\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+    printer->Print(*vars,
+                   "// replace default version of method with split streamed\n"
+                   "virtual ::grpc::Status Streamed$Method$("
+                   "::grpc::ServerContext* context, "
+                   "::grpc::ServerSplitStreamer< "
+                   "$Request$,$Response$>* server_split_streamer)"
+                   " = 0;\n");
+    printer->Outdent();
+    printer->Print(*vars, "};\n");
+  }
+}
+
+void PrintHeaderServerMethodGeneric(
+    grpc_generator::Printer *printer, const grpc_generator::Method *method,
+    std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  printer->Print(*vars, "template <class BaseClass>\n");
+  printer->Print(*vars,
+                 "class WithGenericMethod_$Method$ : public BaseClass {\n");
+  printer->Print(
+      " private:\n"
+      "  void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
+  printer->Print(" public:\n");
+  printer->Indent();
+  printer->Print(*vars,
+                 "WithGenericMethod_$Method$() {\n"
+                 "  ::grpc::Service::MarkMethodGeneric($Idx$);\n"
+                 "}\n");
+  printer->Print(*vars,
+                 "~WithGenericMethod_$Method$() override {\n"
+                 "  BaseClassMustBeDerivedFromService(this);\n"
+                 "}\n");
+  if (method->NoStreaming()) {
+    printer->Print(
+        *vars,
+        "// disable synchronous version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, const $Request$* request, "
+        "$Response$* response) final override {\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+  } else if (ClientOnlyStreaming(method)) {
+    printer->Print(
+        *vars,
+        "// disable synchronous version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, "
+        "::grpc::ServerReader< $Request$>* reader, "
+        "$Response$* response) final override {\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+  } else if (ServerOnlyStreaming(method)) {
+    printer->Print(
+        *vars,
+        "// disable synchronous version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, const $Request$* request, "
+        "::grpc::ServerWriter< $Response$>* writer) final override "
+        "{\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+  } else if (method->BidiStreaming()) {
+    printer->Print(
+        *vars,
+        "// disable synchronous version of this method\n"
+        "::grpc::Status $Method$("
+        "::grpc::ServerContext* context, "
+        "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
+        "final override {\n"
+        "  abort();\n"
+        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+        "}\n");
+  }
+  printer->Outdent();
+  printer->Print(*vars, "};\n");
+}
+
+void PrintHeaderService(grpc_generator::Printer *printer,
+                        const grpc_generator::Service *service,
+                        std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Service"] = service->name();
+
+  printer->Print(service->GetLeadingComments("//").c_str());
+  printer->Print(*vars,
+                 "class $Service$ final {\n"
+                 " public:\n");
+  printer->Indent();
+
+  // Service metadata
+  printer->Print(*vars,
+                 "static constexpr char const* service_full_name() {\n"
+                 "  return \"$Package$$Service$\";\n"
+                 "}\n");
+
+  // Client side
+  printer->Print(
+      "class StubInterface {\n"
+      " public:\n");
+  printer->Indent();
+  printer->Print("virtual ~StubInterface() {}\n");
+  for (int i = 0; i < service->method_count(); ++i) {
+    printer->Print(service->method(i)->GetLeadingComments("//").c_str());
+    PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
+                                      true);
+    printer->Print(service->method(i)->GetTrailingComments("//").c_str());
+  }
+  printer->Outdent();
+  printer->Print("private:\n");
+  printer->Indent();
+  for (int i = 0; i < service->method_count(); ++i) {
+    PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
+                                      false);
+  }
+  printer->Outdent();
+  printer->Print("};\n");
+  printer->Print(
+      "class Stub final : public StubInterface"
+      " {\n public:\n");
+  printer->Indent();
+  printer->Print(
+      "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
+      "channel);\n");
+  for (int i = 0; i < service->method_count(); ++i) {
+    PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
+  }
+  printer->Outdent();
+  printer->Print("\n private:\n");
+  printer->Indent();
+  printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
+  for (int i = 0; i < service->method_count(); ++i) {
+    PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
+  }
+  for (int i = 0; i < service->method_count(); ++i) {
+    PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
+  }
+  printer->Outdent();
+  printer->Print("};\n");
+  printer->Print(
+      "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
+      "::grpc::ChannelInterface>& channel, "
+      "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
+
+  printer->Print("\n");
+
+  // Server side - base
+  printer->Print(
+      "class Service : public ::grpc::Service {\n"
+      " public:\n");
+  printer->Indent();
+  printer->Print("Service();\n");
+  printer->Print("virtual ~Service();\n");
+  for (int i = 0; i < service->method_count(); ++i) {
+    PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
+  }
+  printer->Outdent();
+  printer->Print("};\n");
+
+  // Server side - Asynchronous
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["Idx"] = as_string(i);
+    PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
+  }
+
+  printer->Print("typedef ");
+
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["method_name"] = service->method(i).get()->name();
+    printer->Print(*vars, "WithAsyncMethod_$method_name$<");
+  }
+  printer->Print("Service");
+  for (int i = 0; i < service->method_count(); ++i) {
+    printer->Print(" >");
+  }
+  printer->Print(" AsyncService;\n");
+
+  // Server side - Generic
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["Idx"] = as_string(i);
+    PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
+  }
+
+  // Server side - Streamed Unary
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["Idx"] = as_string(i);
+    PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(),
+                                         vars);
+  }
+
+  printer->Print("typedef ");
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["method_name"] = service->method(i).get()->name();
+    if (service->method(i)->NoStreaming()) {
+      printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
+    }
+  }
+  printer->Print("Service");
+  for (int i = 0; i < service->method_count(); ++i) {
+    if (service->method(i)->NoStreaming()) {
+      printer->Print(" >");
+    }
+  }
+  printer->Print(" StreamedUnaryService;\n");
+
+  // Server side - controlled server-side streaming
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["Idx"] = as_string(i);
+    PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(),
+                                          vars);
+  }
+
+  printer->Print("typedef ");
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["method_name"] = service->method(i).get()->name();
+    auto method = service->method(i);
+    if (ServerOnlyStreaming(method.get())) {
+      printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
+    }
+  }
+  printer->Print("Service");
+  for (int i = 0; i < service->method_count(); ++i) {
+    auto method = service->method(i);
+    if (ServerOnlyStreaming(method.get())) {
+      printer->Print(" >");
+    }
+  }
+  printer->Print(" SplitStreamedService;\n");
+
+  // Server side - typedef for controlled both unary and server-side streaming
+  printer->Print("typedef ");
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["method_name"] = service->method(i).get()->name();
+    auto method = service->method(i);
+    if (ServerOnlyStreaming(method.get())) {
+      printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
+    }
+    if (service->method(i)->NoStreaming()) {
+      printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
+    }
+  }
+  printer->Print("Service");
+  for (int i = 0; i < service->method_count(); ++i) {
+    auto method = service->method(i);
+    if (service->method(i)->NoStreaming() ||
+        ServerOnlyStreaming(method.get())) {
+      printer->Print(" >");
+    }
+  }
+  printer->Print(" StreamedService;\n");
+
+  printer->Outdent();
+  printer->Print("};\n");
+  printer->Print(service->GetTrailingComments("//").c_str());
+}
+
+grpc::string GetHeaderServices(grpc_generator::File *file,
+                               const Parameters &params) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+    // Package string is empty or ends with a dot. It is used to fully qualify
+    // method names.
+    vars["Package"] = file->package();
+    if (!file->package().empty()) {
+      vars["Package"].append(".");
+    }
+
+    if (!params.services_namespace.empty()) {
+      vars["services_namespace"] = params.services_namespace;
+      printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
+    }
+
+    for (int i = 0; i < file->service_count(); ++i) {
+      PrintHeaderService(printer.get(), file->service(i).get(), &vars);
+      printer->Print("\n");
+    }
+
+    if (!params.services_namespace.empty()) {
+      printer->Print(vars, "}  // namespace $services_namespace$\n\n");
+    }
+  }
+  return output;
+}
+
+grpc::string GetHeaderEpilogue(grpc_generator::File *file,
+                               const Parameters & /*params*/) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+
+    vars["filename"] = file->filename();
+    vars["filename_identifier"] = FilenameIdentifier(file->filename());
+
+    if (!file->package().empty()) {
+      std::vector<grpc::string> parts = file->package_parts();
+
+      for (auto part = parts.rbegin(); part != parts.rend(); part++) {
+        vars["part"] = *part;
+        printer->Print(vars, "}  // namespace $part$\n");
+      }
+      printer->Print(vars, "\n");
+    }
+
+    printer->Print(vars, "\n");
+    printer->Print(vars, "#endif  // GRPC_$filename_identifier$__INCLUDED\n");
+
+    printer->Print(file->GetTrailingComments("//").c_str());
+  }
+  return output;
+}
+
+grpc::string GetSourcePrologue(grpc_generator::File *file,
+                               const Parameters & /*params*/) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+
+    vars["filename"] = file->filename();
+    vars["filename_base"] = file->filename_without_ext();
+    vars["message_header_ext"] = message_header_ext();
+    vars["service_header_ext"] = service_header_ext();
+
+    printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
+    printer->Print(vars,
+                   "// If you make any local change, they will be lost.\n");
+    printer->Print(vars, "// source: $filename$\n\n");
+
+    printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
+    printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
+    printer->Print(vars, "\n");
+  }
+  return output;
+}
+
+grpc::string GetSourceIncludes(grpc_generator::File *file,
+                               const Parameters &params) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+
+    static const char *headers_strs[] = {
+        "grpc++/impl/codegen/async_stream.h",
+        "grpc++/impl/codegen/async_unary_call.h",
+        "grpc++/impl/codegen/channel_interface.h",
+        "grpc++/impl/codegen/client_unary_call.h",
+        "grpc++/impl/codegen/method_handler_impl.h",
+        "grpc++/impl/codegen/rpc_service_method.h",
+        "grpc++/impl/codegen/service_type.h",
+        "grpc++/impl/codegen/sync_stream.h"};
+    std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
+    PrintIncludes(printer.get(), headers, params);
+
+    if (!file->package().empty()) {
+      std::vector<grpc::string> parts = file->package_parts();
+
+      for (auto part = parts.begin(); part != parts.end(); part++) {
+        vars["part"] = *part;
+        printer->Print(vars, "namespace $part$ {\n");
+      }
+    }
+
+    printer->Print(vars, "\n");
+  }
+  return output;
+}
+
+void PrintSourceClientMethod(grpc_generator::Printer *printer,
+                             const grpc_generator::Method *method,
+                             std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  struct {
+    grpc::string prefix;
+    grpc::string start;          // bool literal expressed as string
+    grpc::string method_params;  // extra arguments to method
+    grpc::string create_args;    // extra arguments to creator
+  } async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
+                        {"PrepareAsync", "false", "", ", nullptr"}};
+  if (method->NoStreaming()) {
+    printer->Print(*vars,
+                   "::grpc::Status $ns$$Service$::Stub::$Method$("
+                   "::grpc::ClientContext* context, "
+                   "const $Request$& request, $Response$* response) {\n");
+    printer->Print(*vars,
+                   "  return ::grpc::internal::BlockingUnaryCall"
+                   "(channel_.get(), rpcmethod_$Method$_, "
+                   "context, request, response);\n}\n\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+      auto& async_prefix = async_prefixes[i];
+      (*vars)["AsyncPrefix"] = async_prefix.prefix;
+      (*vars)["AsyncStart"] = async_prefix.start;
+      printer->Print(*vars,
+                     "::grpc::ClientAsyncResponseReader< $Response$>* "
+                     "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
+                     "ClientContext* context, "
+                     "const $Request$& request, "
+                     "::grpc::CompletionQueue* cq) {\n");
+      printer->Print(
+          *vars,
+          "  return "
+          "::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
+          "::Create(channel_.get(), cq, "
+          "rpcmethod_$Method$_, "
+          "context, request, $AsyncStart$);\n"
+          "}\n\n");
+    }
+  } else if (ClientOnlyStreaming(method)) {
+    printer->Print(*vars,
+                   "::grpc::ClientWriter< $Request$>* "
+                   "$ns$$Service$::Stub::$Method$Raw("
+                   "::grpc::ClientContext* context, $Response$* response) {\n");
+    printer->Print(
+        *vars,
+        "  return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
+        "channel_.get(), "
+        "rpcmethod_$Method$_, "
+        "context, response);\n"
+        "}\n\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+      auto& async_prefix = async_prefixes[i];
+      (*vars)["AsyncPrefix"] = async_prefix.prefix;
+      (*vars)["AsyncStart"] = async_prefix.start;
+      (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+      (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
+      printer->Print(*vars,
+                     "::grpc::ClientAsyncWriter< $Request$>* "
+                     "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
+                     "::grpc::ClientContext* context, $Response$* response, "
+                     "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+      printer->Print(
+          *vars,
+          "  return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
+          "::Create(channel_.get(), cq, "
+          "rpcmethod_$Method$_, "
+          "context, response, $AsyncStart$$AsyncCreateArgs$);\n"
+          "}\n\n");
+    }
+  } else if (ServerOnlyStreaming(method)) {
+    printer->Print(
+        *vars,
+        "::grpc::ClientReader< $Response$>* "
+        "$ns$$Service$::Stub::$Method$Raw("
+        "::grpc::ClientContext* context, const $Request$& request) {\n");
+    printer->Print(
+        *vars,
+        "  return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
+        "channel_.get(), "
+        "rpcmethod_$Method$_, "
+        "context, request);\n"
+        "}\n\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+      auto& async_prefix = async_prefixes[i];
+      (*vars)["AsyncPrefix"] = async_prefix.prefix;
+      (*vars)["AsyncStart"] = async_prefix.start;
+      (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+      (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
+      printer->Print(
+          *vars,
+          "::grpc::ClientAsyncReader< $Response$>* "
+          "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
+          "::grpc::ClientContext* context, const $Request$& request, "
+          "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+      printer->Print(
+          *vars,
+          "  return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
+          "::Create(channel_.get(), cq, "
+          "rpcmethod_$Method$_, "
+          "context, request, $AsyncStart$$AsyncCreateArgs$);\n"
+          "}\n\n");
+    }
+  } else if (method->BidiStreaming()) {
+    printer->Print(
+        *vars,
+        "::grpc::ClientReaderWriter< $Request$, $Response$>* "
+        "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
+    printer->Print(*vars,
+                   "  return ::grpc::internal::ClientReaderWriterFactory< "
+                   "$Request$, $Response$>::Create("
+                   "channel_.get(), "
+                   "rpcmethod_$Method$_, "
+                   "context);\n"
+                   "}\n\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+      auto& async_prefix = async_prefixes[i];
+      (*vars)["AsyncPrefix"] = async_prefix.prefix;
+      (*vars)["AsyncStart"] = async_prefix.start;
+      (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+      (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
+      printer->Print(*vars,
+                     "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
+                     "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
+                     "ClientContext* context, "
+                     "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+      printer->Print(*vars,
+                     "  return "
+                     "::grpc::internal::ClientAsyncReaderWriterFactory< "
+                     "$Request$, $Response$>::Create("
+                     "channel_.get(), cq, "
+                     "rpcmethod_$Method$_, "
+                     "context, $AsyncStart$$AsyncCreateArgs$);\n"
+                     "}\n\n");
+    }
+  }
+}
+
+void PrintSourceServerMethod(grpc_generator::Printer *printer,
+                             const grpc_generator::Method *method,
+                             std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  if (method->NoStreaming()) {
+    printer->Print(*vars,
+                   "::grpc::Status $ns$$Service$::Service::$Method$("
+                   "::grpc::ServerContext* context, "
+                   "const $Request$* request, $Response$* response) {\n");
+    printer->Print("  (void) context;\n");
+    printer->Print("  (void) request;\n");
+    printer->Print("  (void) response;\n");
+    printer->Print(
+        "  return ::grpc::Status("
+        "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
+    printer->Print("}\n\n");
+  } else if (ClientOnlyStreaming(method)) {
+    printer->Print(*vars,
+                   "::grpc::Status $ns$$Service$::Service::$Method$("
+                   "::grpc::ServerContext* context, "
+                   "::grpc::ServerReader< $Request$>* reader, "
+                   "$Response$* response) {\n");
+    printer->Print("  (void) context;\n");
+    printer->Print("  (void) reader;\n");
+    printer->Print("  (void) response;\n");
+    printer->Print(
+        "  return ::grpc::Status("
+        "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
+    printer->Print("}\n\n");
+  } else if (ServerOnlyStreaming(method)) {
+    printer->Print(*vars,
+                   "::grpc::Status $ns$$Service$::Service::$Method$("
+                   "::grpc::ServerContext* context, "
+                   "const $Request$* request, "
+                   "::grpc::ServerWriter< $Response$>* writer) {\n");
+    printer->Print("  (void) context;\n");
+    printer->Print("  (void) request;\n");
+    printer->Print("  (void) writer;\n");
+    printer->Print(
+        "  return ::grpc::Status("
+        "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
+    printer->Print("}\n\n");
+  } else if (method->BidiStreaming()) {
+    printer->Print(*vars,
+                   "::grpc::Status $ns$$Service$::Service::$Method$("
+                   "::grpc::ServerContext* context, "
+                   "::grpc::ServerReaderWriter< $Response$, $Request$>* "
+                   "stream) {\n");
+    printer->Print("  (void) context;\n");
+    printer->Print("  (void) stream;\n");
+    printer->Print(
+        "  return ::grpc::Status("
+        "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
+    printer->Print("}\n\n");
+  }
+}
+
+void PrintSourceService(grpc_generator::Printer *printer,
+                        const grpc_generator::Service *service,
+                        std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Service"] = service->name();
+
+  if (service->method_count() > 0) {
+    printer->Print(*vars,
+                   "static const char* $prefix$$Service$_method_names[] = {\n");
+    for (int i = 0; i < service->method_count(); ++i) {
+      (*vars)["Method"] = service->method(i).get()->name();
+      printer->Print(*vars, "  \"/$Package$$Service$/$Method$\",\n");
+    }
+    printer->Print(*vars, "};\n\n");
+  }
+
+  printer->Print(*vars,
+                 "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
+                 "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
+                 "const ::grpc::StubOptions& options) {\n"
+                 "  std::unique_ptr< $ns$$Service$::Stub> stub(new "
+                 "$ns$$Service$::Stub(channel));\n"
+                 "  return stub;\n"
+                 "}\n\n");
+  printer->Print(*vars,
+                 "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
+                 "::grpc::ChannelInterface>& channel)\n");
+  printer->Indent();
+  printer->Print(": channel_(channel)");
+  for (int i = 0; i < service->method_count(); ++i) {
+    auto method = service->method(i);
+    (*vars)["Method"] = method->name();
+    (*vars)["Idx"] = as_string(i);
+    if (method->NoStreaming()) {
+      (*vars)["StreamingType"] = "NORMAL_RPC";
+      // NOTE: There is no reason to consider streamed-unary as a separate
+      // category here since this part is setting up the client-side stub
+      // and this appears as a NORMAL_RPC from the client-side.
+    } else if (ClientOnlyStreaming(method.get())) {
+      (*vars)["StreamingType"] = "CLIENT_STREAMING";
+    } else if (ServerOnlyStreaming(method.get())) {
+      (*vars)["StreamingType"] = "SERVER_STREAMING";
+    } else {
+      (*vars)["StreamingType"] = "BIDI_STREAMING";
+    }
+    printer->Print(*vars,
+                   ", rpcmethod_$Method$_("
+                   "$prefix$$Service$_method_names[$Idx$], "
+                   "::grpc::internal::RpcMethod::$StreamingType$, "
+                   "channel"
+                   ")\n");
+  }
+  printer->Print("{}\n\n");
+  printer->Outdent();
+
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["Idx"] = as_string(i);
+    PrintSourceClientMethod(printer, service->method(i).get(), vars);
+  }
+
+  printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
+  printer->Indent();
+  for (int i = 0; i < service->method_count(); ++i) {
+    auto method = service->method(i);
+    (*vars)["Idx"] = as_string(i);
+    (*vars)["Method"] = method->name();
+    (*vars)["Request"] = method->input_type_name();
+    (*vars)["Response"] = method->output_type_name();
+    if (method->NoStreaming()) {
+      printer->Print(
+          *vars,
+          "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+          "    $prefix$$Service$_method_names[$Idx$],\n"
+          "    ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
+          "    new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
+          "$Request$, "
+          "$Response$>(\n"
+          "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
+    } else if (ClientOnlyStreaming(method.get())) {
+      printer->Print(
+          *vars,
+          "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+          "    $prefix$$Service$_method_names[$Idx$],\n"
+          "    ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
+          "    new ::grpc::internal::ClientStreamingHandler< "
+          "$ns$$Service$::Service, $Request$, $Response$>(\n"
+          "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
+    } else if (ServerOnlyStreaming(method.get())) {
+      printer->Print(
+          *vars,
+          "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+          "    $prefix$$Service$_method_names[$Idx$],\n"
+          "    ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
+          "    new ::grpc::internal::ServerStreamingHandler< "
+          "$ns$$Service$::Service, $Request$, $Response$>(\n"
+          "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
+    } else if (method->BidiStreaming()) {
+      printer->Print(
+          *vars,
+          "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+          "    $prefix$$Service$_method_names[$Idx$],\n"
+          "    ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
+          "    new ::grpc::internal::BidiStreamingHandler< "
+          "$ns$$Service$::Service, $Request$, $Response$>(\n"
+          "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
+    }
+  }
+  printer->Outdent();
+  printer->Print(*vars, "}\n\n");
+  printer->Print(*vars,
+                 "$ns$$Service$::Service::~Service() {\n"
+                 "}\n\n");
+  for (int i = 0; i < service->method_count(); ++i) {
+    (*vars)["Idx"] = as_string(i);
+    PrintSourceServerMethod(printer, service->method(i).get(), vars);
+  }
+}
+
+grpc::string GetSourceServices(grpc_generator::File *file,
+                               const Parameters &params) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+    // Package string is empty or ends with a dot. It is used to fully qualify
+    // method names.
+    vars["Package"] = file->package();
+    if (!file->package().empty()) {
+      vars["Package"].append(".");
+    }
+    if (!params.services_namespace.empty()) {
+      vars["ns"] = params.services_namespace + "::";
+      vars["prefix"] = params.services_namespace;
+    } else {
+      vars["ns"] = "";
+      vars["prefix"] = "";
+    }
+
+    for (int i = 0; i < file->service_count(); ++i) {
+      PrintSourceService(printer.get(), file->service(i).get(), &vars);
+      printer->Print("\n");
+    }
+  }
+  return output;
+}
+
+grpc::string GetSourceEpilogue(grpc_generator::File *file,
+                               const Parameters & /*params*/) {
+  grpc::string temp;
+
+  if (!file->package().empty()) {
+    std::vector<grpc::string> parts = file->package_parts();
+
+    for (auto part = parts.begin(); part != parts.end(); part++) {
+      temp.append("}  // namespace ");
+      temp.append(*part);
+      temp.append("\n");
+    }
+    temp.append("\n");
+  }
+
+  return temp;
+}
+
+// TODO(mmukhi): Make sure we need parameters or not.
+grpc::string GetMockPrologue(grpc_generator::File *file,
+                             const Parameters & /*params*/) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+
+    vars["filename"] = file->filename();
+    vars["filename_base"] = file->filename_without_ext();
+    vars["message_header_ext"] = message_header_ext();
+    vars["service_header_ext"] = service_header_ext();
+
+    printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
+    printer->Print(vars,
+                   "// If you make any local change, they will be lost.\n");
+    printer->Print(vars, "// source: $filename$\n\n");
+
+    printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
+    printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
+    printer->Print(vars, file->additional_headers().c_str());
+    printer->Print(vars, "\n");
+  }
+  return output;
+}
+
+// TODO(mmukhi): Add client-stream and completion-queue headers.
+grpc::string GetMockIncludes(grpc_generator::File *file,
+                             const Parameters &params) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+
+    static const char *headers_strs[] = {
+        "grpc++/impl/codegen/async_stream.h",
+        "grpc++/impl/codegen/sync_stream.h",
+        "gmock/gmock.h",
+    };
+    std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
+    PrintIncludes(printer.get(), headers, params);
+
+    if (!file->package().empty()) {
+      std::vector<grpc::string> parts = file->package_parts();
+
+      for (auto part = parts.begin(); part != parts.end(); part++) {
+        vars["part"] = *part;
+        printer->Print(vars, "namespace $part$ {\n");
+      }
+    }
+
+    printer->Print(vars, "\n");
+  }
+  return output;
+}
+
+void PrintMockClientMethods(grpc_generator::Printer *printer,
+                            const grpc_generator::Method *method,
+                            std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Method"] = method->name();
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+
+  struct {
+    grpc::string prefix;
+    grpc::string method_params;  // extra arguments to method
+    int extra_method_param_count;
+  } async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
+
+  if (method->NoStreaming()) {
+    printer->Print(
+        *vars,
+        "MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
+        "const $Request$& request, $Response$* response));\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+      auto& async_prefix = async_prefixes[i];
+      (*vars)["AsyncPrefix"] = async_prefix.prefix;
+      printer->Print(
+          *vars,
+          "MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
+          "::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
+          "(::grpc::ClientContext* context, const $Request$& request, "
+          "::grpc::CompletionQueue* cq));\n");
+    }
+  } else if (ClientOnlyStreaming(method)) {
+    printer->Print(
+        *vars,
+        "MOCK_METHOD2($Method$Raw, "
+        "::grpc::ClientWriterInterface< $Request$>*"
+        "(::grpc::ClientContext* context, $Response$* response));\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+      auto& async_prefix = async_prefixes[i];
+      (*vars)["AsyncPrefix"] = async_prefix.prefix;
+      (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+      (*vars)["MockArgs"] =
+        flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
+      printer->Print(*vars,
+                     "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
+                     "::grpc::ClientAsyncWriterInterface< $Request$>*"
+                     "(::grpc::ClientContext* context, $Response$* response, "
+                     "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
+    }
+  } else if (ServerOnlyStreaming(method)) {
+    printer->Print(
+        *vars,
+        "MOCK_METHOD2($Method$Raw, "
+        "::grpc::ClientReaderInterface< $Response$>*"
+        "(::grpc::ClientContext* context, const $Request$& request));\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+      auto& async_prefix = async_prefixes[i];
+      (*vars)["AsyncPrefix"] = async_prefix.prefix;
+      (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+      (*vars)["MockArgs"] =
+          flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
+      printer->Print(
+          *vars,
+          "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
+          "::grpc::ClientAsyncReaderInterface< $Response$>*"
+          "(::grpc::ClientContext* context, const $Request$& request, "
+          "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
+    }
+  } else if (method->BidiStreaming()) {
+    printer->Print(
+        *vars,
+        "MOCK_METHOD1($Method$Raw, "
+        "::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
+        "(::grpc::ClientContext* context));\n");
+    for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+      auto& async_prefix = async_prefixes[i];
+      (*vars)["AsyncPrefix"] = async_prefix.prefix;
+      (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+      (*vars)["MockArgs"] =
+          flatbuffers::NumToString(2 + async_prefix.extra_method_param_count);
+      printer->Print(
+          *vars,
+          "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
+          "::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
+          "(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
+          "$AsyncMethodParams$));\n");
+    }
+  }
+}
+
+void PrintMockService(grpc_generator::Printer *printer,
+                      const grpc_generator::Service *service,
+                      std::map<grpc::string, grpc::string> *vars) {
+  (*vars)["Service"] = service->name();
+
+  printer->Print(*vars,
+                 "class Mock$Service$Stub : public $Service$::StubInterface {\n"
+                 " public:\n");
+  printer->Indent();
+  for (int i = 0; i < service->method_count(); ++i) {
+    PrintMockClientMethods(printer, service->method(i).get(), vars);
+  }
+  printer->Outdent();
+  printer->Print("};\n");
+}
+
+grpc::string GetMockServices(grpc_generator::File *file,
+                             const Parameters &params) {
+  grpc::string output;
+  {
+    // Scope the output stream so it closes and finalizes output to the string.
+    auto printer = file->CreatePrinter(&output);
+    std::map<grpc::string, grpc::string> vars;
+    // Package string is empty or ends with a dot. It is used to fully qualify
+    // method names.
+    vars["Package"] = file->package();
+    if (!file->package().empty()) {
+      vars["Package"].append(".");
+    }
+
+    if (!params.services_namespace.empty()) {
+      vars["services_namespace"] = params.services_namespace;
+      printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
+    }
+
+    for (int i = 0; i < file->service_count(); i++) {
+      PrintMockService(printer.get(), file->service(i).get(), &vars);
+      printer->Print("\n");
+    }
+
+    if (!params.services_namespace.empty()) {
+      printer->Print(vars, "} // namespace $services_namespace$\n\n");
+    }
+  }
+  return output;
+}
+
+grpc::string GetMockEpilogue(grpc_generator::File *file,
+                             const Parameters & /*params*/) {
+  grpc::string temp;
+
+  if (!file->package().empty()) {
+    std::vector<grpc::string> parts = file->package_parts();
+
+    for (auto part = parts.begin(); part != parts.end(); part++) {
+      temp.append("} // namespace ");
+      temp.append(*part);
+      temp.append("\n");
+    }
+    temp.append("\n");
+  }
+
+  return temp;
+}
+
+}  // namespace grpc_cpp_generator