2 * Copyright 2014 Google Inc. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 // independent from idl_parser, since this code is not needed for most clients
19 #include "flatbuffers/flatbuffers.h"
20 #include "flatbuffers/idl.h"
21 #include "flatbuffers/util.h"
22 #include "flatbuffers/code_generators.h"
24 #include "src/compiler/cpp_generator.h"
25 #include "src/compiler/go_generator.h"
29 #pragma warning(disable: 4512) // C4512: 'class' : assignment operator could not be generated
32 namespace flatbuffers {
34 class FlatBufMethod : public grpc_generator::Method {
36 enum Streaming { kNone, kClient, kServer, kBiDi };
38 FlatBufMethod(const RPCCall *method)
41 auto val = method_->attributes.Lookup("streaming");
43 if (val->constant == "client") streaming_ = kClient;
44 if (val->constant == "server") streaming_ = kServer;
45 if (val->constant == "bidi") streaming_ = kBiDi;
49 grpc::string GetLeadingComments(const grpc::string) const {
52 grpc::string GetTrailingComments(const grpc::string) const {
55 std::vector<grpc::string> GetAllComments() const {
56 return std::vector<grpc::string>();
59 std::string name() const { return method_->name; }
61 std::string GRPCType(const StructDef &sd) const {
62 return "flatbuffers::BufferRef<" + sd.name + ">";
65 std::string get_input_type_name() const {
66 return (*method_->request).name;
68 std::string get_output_type_name() const {
69 return (*method_->response).name;
72 bool get_module_and_message_path_input(
73 grpc::string * /*str*/, grpc::string /*generator_file_name*/,
74 bool /*generate_in_pb2_grpc*/, grpc::string /*import_prefix*/) const {
78 bool get_module_and_message_path_output(
79 grpc::string * /*str*/, grpc::string /*generator_file_name*/,
80 bool /*generate_in_pb2_grpc*/, grpc::string /*import_prefix*/) const {
84 std::string input_type_name() const {
85 return GRPCType(*method_->request);
88 std::string output_type_name() const {
89 return GRPCType(*method_->response);
92 bool NoStreaming() const { return streaming_ == kNone; }
93 bool ClientStreaming() const { return streaming_ == kClient; }
94 bool ServerStreaming() const { return streaming_ == kServer; }
95 bool BidiStreaming() const { return streaming_ == kBiDi; }
98 const RPCCall *method_;
102 class FlatBufService : public grpc_generator::Service {
104 FlatBufService(const ServiceDef *service) : service_(service) {}
106 grpc::string GetLeadingComments(const grpc::string) const {
109 grpc::string GetTrailingComments(const grpc::string) const {
112 std::vector<grpc::string> GetAllComments() const {
113 return std::vector<grpc::string>();
116 std::string name() const { return service_->name; }
118 int method_count() const {
119 return static_cast<int>(service_->calls.vec.size());
122 std::unique_ptr<const grpc_generator::Method> method(int i) const {
123 return std::unique_ptr<const grpc_generator::Method>(
124 new FlatBufMethod(service_->calls.vec[i]));
128 const ServiceDef *service_;
131 class FlatBufPrinter : public grpc_generator::Printer {
133 FlatBufPrinter(std::string *str)
134 : str_(str), escape_char_('$'), indent_(0) {}
136 void Print(const std::map<std::string, std::string> &vars,
137 const char *string_template) {
138 std::string s = string_template;
139 // Replace any occurrences of strings in "vars" that are surrounded
140 // by the escape character by what they're mapped to.
142 while ((pos = s.find(escape_char_)) != std::string::npos) {
143 // Found an escape char, must also find the closing one.
144 size_t pos2 = s.find(escape_char_, pos + 1);
145 // If placeholder not closed, ignore.
146 if (pos2 == std::string::npos) break;
147 auto it = vars.find(s.substr(pos + 1, pos2 - pos - 1));
148 // If unknown placeholder, ignore.
149 if (it == vars.end()) break;
150 // Subtitute placeholder.
151 s.replace(pos, pos2 - pos + 1, it->second);
156 void Print(const char *s) {
157 if (s == nullptr || std::strlen(s) == 0) {
160 // Add this string, but for each part separated by \n, add indentation.
162 // Current indentation.
163 str_->insert(str_->end(), indent_ * 2, ' ');
164 // See if this contains more than one line.
165 const char * lf = strchr(s, '\n');
167 (*str_) += std::string(s, lf + 1);
169 if (!*s) break; // Only continue if there's more lines.
177 void Indent() { indent_++; }
178 void Outdent() { indent_--; assert(indent_ >= 0); }
186 class FlatBufFile : public grpc_generator::File {
194 const Parser &parser, const std::string &file_name, Language language)
195 : parser_(parser), file_name_(file_name), language_(language) {}
196 FlatBufFile &operator=(const FlatBufFile &);
198 grpc::string GetLeadingComments(const grpc::string) const {
201 grpc::string GetTrailingComments(const grpc::string) const {
204 std::vector<grpc::string> GetAllComments() const {
205 return std::vector<grpc::string>();
208 std::string filename() const { return file_name_; }
209 std::string filename_without_ext() const {
210 return StripExtension(file_name_);
213 std::string message_header_ext() const { return "_generated.h"; }
214 std::string service_header_ext() const { return ".grpc.fb.h"; }
216 std::string package() const {
217 return parser_.namespaces_.back()->GetFullyQualifiedName("");
220 std::vector<std::string> package_parts() const {
221 return parser_.namespaces_.back()->components;
224 std::string additional_headers() const {
227 return "#include \"flatbuffers/grpc.h\"\n";
230 return "import \"github.com/google/flatbuffers/go\"";
236 int service_count() const {
237 return static_cast<int>(parser_.services_.vec.size());
240 std::unique_ptr<const grpc_generator::Service> service(int i) const {
241 return std::unique_ptr<const grpc_generator::Service> (
242 new FlatBufService(parser_.services_.vec[i]));
245 std::unique_ptr<grpc_generator::Printer> CreatePrinter(std::string *str) const {
246 return std::unique_ptr<grpc_generator::Printer>(
247 new FlatBufPrinter(str));
251 const Parser &parser_;
252 const std::string &file_name_;
253 const Language language_;
256 class GoGRPCGenerator : public flatbuffers::BaseGenerator {
258 GoGRPCGenerator(const Parser &parser, const std::string &path,
259 const std::string &file_name)
260 : BaseGenerator(parser, path, file_name, "", "" /*Unused*/),
261 parser_(parser), path_(path), file_name_(file_name) {}
264 FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageGo);
265 grpc_go_generator::Parameters p;
266 p.custom_method_io_type = "flatbuffers.Builder";
267 for (int i = 0; i < file.service_count(); i++) {
268 auto service = file.service(i);
269 const Definition *def = parser_.services_.vec[i];
270 p.package_name = LastNamespacePart(*(def->defined_namespace));
271 std::string output = grpc_go_generator::GenerateServiceSource(&file, service.get(), &p);
272 std::string filename = NamespaceDir(*def->defined_namespace) + def->name + "_grpc.go";
273 if (!flatbuffers::SaveFile(filename.c_str(), output, false))
280 const Parser &parser_;
281 const std::string &path_, &file_name_;
284 bool GenerateGoGRPC(const Parser &parser,
285 const std::string &path,
286 const std::string &file_name) {
288 for (auto it = parser.services_.vec.begin();
289 it != parser.services_.vec.end(); ++it) {
290 if (!(*it)->generated) nservices++;
292 if (!nservices) return true;
293 return GoGRPCGenerator(parser, path, file_name).generate();
296 bool GenerateCppGRPC(const Parser &parser,
297 const std::string &path,
298 const std::string &file_name) {
301 for (auto it = parser.services_.vec.begin();
302 it != parser.services_.vec.end(); ++it) {
303 if (!(*it)->generated) nservices++;
305 if (!nservices) return true;
307 grpc_cpp_generator::Parameters generator_parameters;
308 // TODO(wvo): make the other parameters in this struct configurable.
309 generator_parameters.use_system_headers = true;
311 FlatBufFile fbfile(parser, file_name, FlatBufFile::kLanguageCpp);
313 std::string header_code =
314 grpc_cpp_generator::GetHeaderPrologue(&fbfile, generator_parameters) +
315 grpc_cpp_generator::GetHeaderIncludes(&fbfile, generator_parameters) +
316 grpc_cpp_generator::GetHeaderServices(&fbfile, generator_parameters) +
317 grpc_cpp_generator::GetHeaderEpilogue(&fbfile, generator_parameters);
319 std::string source_code =
320 grpc_cpp_generator::GetSourcePrologue(&fbfile, generator_parameters) +
321 grpc_cpp_generator::GetSourceIncludes(&fbfile, generator_parameters) +
322 grpc_cpp_generator::GetSourceServices(&fbfile, generator_parameters) +
323 grpc_cpp_generator::GetSourceEpilogue(&fbfile, generator_parameters);
325 return flatbuffers::SaveFile((path + file_name + ".grpc.fb.h").c_str(),
326 header_code, false) &&
327 flatbuffers::SaveFile((path + file_name + ".grpc.fb.cc").c_str(),
331 } // namespace flatbuffers
333 #if defined(_MSC_VER)