• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 
12 #include "google/protobuf/compiler/cpp/service.h"
13 
14 #include <string>
15 
16 #include "absl/strings/str_cat.h"
17 #include "google/protobuf/compiler/cpp/helpers.h"
18 #include "google/protobuf/descriptor.h"
19 #include "google/protobuf/io/printer.h"
20 
21 namespace google {
22 namespace protobuf {
23 namespace compiler {
24 namespace cpp {
GenerateDeclarations(io::Printer * printer)25 void ServiceGenerator::GenerateDeclarations(io::Printer* printer) {
26   auto vars = printer->WithVars(&vars_);
27   printer->Emit(
28       {
29           {"virts", [&] { GenerateMethodSignatures(kVirtual, printer); }},
30           {"impls", [&] { GenerateMethodSignatures(kNonVirtual, printer); }},
31       },
32       R"cc(
33         class $classname$_Stub;
34         class $dllexport_decl $$classname$ : public ::$proto_ns$::Service {
35          protected:
36           $classname$() = default;
37 
38          public:
39           using Stub = $classname$_Stub;
40 
41           $classname$(const $classname$&) = delete;
42           $classname$& operator=(const $classname$&) = delete;
43           virtual ~$classname$() = default;
44 
45           static const ::$proto_ns$::ServiceDescriptor* descriptor();
46 
47           $virts$;
48 
49           // implements Service ----------------------------------------------
50           const ::$proto_ns$::ServiceDescriptor* GetDescriptor() override;
51 
52           void CallMethod(const ::$proto_ns$::MethodDescriptor* method,
53                           ::$proto_ns$::RpcController* controller,
54                           const ::$proto_ns$::Message* request,
55                           ::$proto_ns$::Message* response,
56                           ::google::protobuf::Closure* done) override;
57 
58           const ::$proto_ns$::Message& GetRequestPrototype(
59               const ::$proto_ns$::MethodDescriptor* method) const override;
60 
61           const ::$proto_ns$::Message& GetResponsePrototype(
62               const ::$proto_ns$::MethodDescriptor* method) const override;
63         };
64 
65         class $dllexport_decl $$classname$_Stub final : public $classname$ {
66          public:
67           $classname$_Stub(::$proto_ns$::RpcChannel* channel);
68           $classname$_Stub(::$proto_ns$::RpcChannel* channel,
69                            ::$proto_ns$::Service::ChannelOwnership ownership);
70 
71           $classname$_Stub(const $classname$_Stub&) = delete;
72           $classname$_Stub& operator=(const $classname$_Stub&) = delete;
73 
74           ~$classname$_Stub() override;
75 
76           inline ::$proto_ns$::RpcChannel* channel() { return channel_; }
77 
78           // implements $classname$ ------------------------------------------
79           $impls$;
80 
81          private:
82           ::$proto_ns$::RpcChannel* channel_;
83           bool owns_channel_;
84         };
85       )cc");
86 }
87 
GenerateMethodSignatures(VirtualOrNot virtual_or_not,io::Printer * printer)88 void ServiceGenerator::GenerateMethodSignatures(VirtualOrNot virtual_or_not,
89                                                 io::Printer* printer) {
90   for (int i = 0; i < descriptor_->method_count(); ++i) {
91     const MethodDescriptor* method = descriptor_->method(i);
92 
93     printer->Emit(
94         {
95             {"name", method->name()},
96             {"input", QualifiedClassName(method->input_type(), *options_)},
97             {"output", QualifiedClassName(method->output_type(), *options_)},
98             {"virtual", virtual_or_not == kVirtual ? "virtual" : ""},
99             {"override", virtual_or_not != kVirtual ? "override" : ""},
100         },
101         // No cc, clang-format does not format this string well due to the
102         // $ override$ substitution.
103         R"(
104           $virtual $void $name$(::$proto_ns$::RpcController* controller,
105                                 const $input$* request,
106                                 $output$* response,
107                                 ::google::protobuf::Closure* done)$ override$;
108         )");
109   }
110 }
111 
112 // ===================================================================
113 
GenerateImplementation(io::Printer * printer)114 void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
115   auto vars = printer->WithVars(&vars_);
116   printer->Emit(
117       {
118           {"index", index_in_metadata_},
119           {"no_impl_methods", [&] { GenerateNotImplementedMethods(printer); }},
120           {"call_method", [&] { GenerateCallMethod(printer); }},
121           {"get_request", [&] { GenerateGetPrototype(kRequest, printer); }},
122           {"get_response", [&] { GenerateGetPrototype(kResponse, printer); }},
123           {"stub_methods", [&] { GenerateStubMethods(printer); }},
124       },
125       R"cc(
126         const ::$proto_ns$::ServiceDescriptor* $classname$::descriptor() {
127           ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);
128           return $file_level_service_descriptors$[$index$];
129         }
130 
131         const ::$proto_ns$::ServiceDescriptor* $classname$::GetDescriptor() {
132           return descriptor();
133         }
134 
135         $no_impl_methods$;
136 
137         $call_method$;
138 
139         $get_request$;
140 
141         $get_response$;
142 
143         $classname$_Stub::$classname$_Stub(::$proto_ns$::RpcChannel* channel)
144             : channel_(channel), owns_channel_(false) {}
145 
146         $classname$_Stub::$classname$_Stub(
147             ::$proto_ns$::RpcChannel* channel,
148             ::$proto_ns$::Service::ChannelOwnership ownership)
149             : channel_(channel),
150               owns_channel_(ownership ==
151                             ::$proto_ns$::Service::STUB_OWNS_CHANNEL) {}
152 
153         $classname$_Stub::~$classname$_Stub() {
154           if (owns_channel_) delete channel_;
155         }
156 
157         $stub_methods$;
158       )cc");
159 }
160 
GenerateNotImplementedMethods(io::Printer * printer)161 void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
162   for (int i = 0; i < descriptor_->method_count(); ++i) {
163     const MethodDescriptor* method = descriptor_->method(i);
164 
165     printer->Emit(
166         {
167             {"name", method->name()},
168             {"input", QualifiedClassName(method->input_type(), *options_)},
169             {"output", QualifiedClassName(method->output_type(), *options_)},
170         },
171         R"cc(
172           void $classname$::$name$(::$proto_ns$::RpcController* controller,
173                                    const $input$*, $output$*, ::google::protobuf::Closure* done) {
174             controller->SetFailed("Method $name$() not implemented.");
175             done->Run();
176           }
177         )cc");
178   }
179 }
180 
GenerateCallMethod(io::Printer * printer)181 void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
182   printer->Emit(
183       {
184           {"index", absl::StrCat(index_in_metadata_)},
185           {"cases", [&] { GenerateCallMethodCases(printer); }},
186       },
187       R"cc(
188         void $classname$::CallMethod(
189             const ::$proto_ns$::MethodDescriptor* method,
190             ::$proto_ns$::RpcController* controller,
191             const ::$proto_ns$::Message* request,
192             ::$proto_ns$::Message* response, ::google::protobuf::Closure* done) {
193           ABSL_DCHECK_EQ(method->service(), $file_level_service_descriptors$[$index$]);
194           switch (method->index()) {
195             $cases$;
196 
197             default:
198               ABSL_LOG(FATAL) << "Bad method index; this should never happen.";
199               break;
200           }
201         }
202       )cc");
203 }
204 
GenerateGetPrototype(RequestOrResponse which,io::Printer * printer)205 void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
206                                             io::Printer* printer) {
207   printer->Emit(
208       {
209           {"which", which == kRequest ? "Request" : "Response"},
210           {"which_type", which == kRequest ? "input" : "output"},
211           {"cases",
212            [&] {
213              for (int i = 0; i < descriptor_->method_count(); ++i) {
214                const MethodDescriptor* method = descriptor_->method(i);
215                const Descriptor* type = which == kRequest
216                                             ? method->input_type()
217                                             : method->output_type();
218 
219                printer->Emit(
220                    {
221                        {"index", absl::StrCat(i)},
222                        {"type", QualifiedClassName(type, *options_)},
223                    },
224                    R"cc(
225                      case $index$:
226                        return $type$::default_instance();
227                    )cc");
228              }
229            }},
230       },
231       R"cc(
232         const ::$proto_ns$::Message& $classname$::Get$which$Prototype(
233             const ::$proto_ns$::MethodDescriptor* method) const {
234           ABSL_DCHECK_EQ(method->service(), descriptor());
235           switch (method->index()) {
236             $cases$;
237 
238             default:
239               ABSL_LOG(FATAL) << "Bad method index; this should never happen.";
240               return *::$proto_ns$::MessageFactory::generated_factory()
241                           ->GetPrototype(method->$which_type$_type());
242           }
243         }
244       )cc");
245 }
246 
GenerateCallMethodCases(io::Printer * printer)247 void ServiceGenerator::GenerateCallMethodCases(io::Printer* printer) {
248   for (int i = 0; i < descriptor_->method_count(); ++i) {
249     const MethodDescriptor* method = descriptor_->method(i);
250     printer->Emit(
251         {
252             {"name", method->name()},
253             {"input", QualifiedClassName(method->input_type(), *options_)},
254             {"output", QualifiedClassName(method->output_type(), *options_)},
255             {"index", absl::StrCat(i)},
256         },
257         R"cc(
258           case $index$:
259             this->$name$(controller,
260                          ::$proto_ns$::DownCastMessage<$input$>(request),
261                          ::$proto_ns$::DownCastMessage<$output$>(response),
262                          done);
263             break;
264         )cc");
265   }
266 }
267 
GenerateStubMethods(io::Printer * printer)268 void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
269   for (int i = 0; i < descriptor_->method_count(); ++i) {
270     const MethodDescriptor* method = descriptor_->method(i);
271 
272     printer->Emit(
273         {
274             {"name", method->name()},
275             {"input", QualifiedClassName(method->input_type(), *options_)},
276             {"output", QualifiedClassName(method->output_type(), *options_)},
277             {"index", absl::StrCat(i)},
278         },
279         R"cc(
280           void $classname$_Stub::$name$(::$proto_ns$::RpcController* controller,
281                                         const $input$* request,
282                                         $output$* response, ::google::protobuf::Closure* done) {
283             channel_->CallMethod(descriptor()->method($index$), controller,
284                                  request, response, done);
285           }
286         )cc");
287   }
288 }
289 
290 }  // namespace cpp
291 }  // namespace compiler
292 }  // namespace protobuf
293 }  // namespace google
294