1 | /* |
2 | * |
3 | * Copyright 2015 gRPC authors. |
4 | * |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | * you may not use this file except in compliance with the License. |
7 | * You may obtain a copy of the License at |
8 | * |
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | * |
11 | * Unless required by applicable law or agreed to in writing, software |
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | * See the License for the specific language governing permissions and |
15 | * limitations under the License. |
16 | * |
17 | */ |
18 | |
19 | #ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H |
20 | #define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H |
21 | |
22 | #include <cstring> |
23 | #include <fstream> |
24 | #include <iostream> |
25 | #include <vector> |
26 | |
27 | #include "src/compiler/config.h" |
28 | #include "src/compiler/generator_helpers.h" |
29 | #include "src/compiler/python_generator.h" |
30 | #include "src/compiler/python_private_generator.h" |
31 | |
32 | using grpc::protobuf::Descriptor; |
33 | using grpc::protobuf::FileDescriptor; |
34 | using grpc::protobuf::MethodDescriptor; |
35 | using grpc::protobuf::ServiceDescriptor; |
36 | using grpc::protobuf::compiler::GeneratorContext; |
37 | using grpc::protobuf::io::CodedOutputStream; |
38 | using grpc::protobuf::io::Printer; |
39 | using grpc::protobuf::io::StringOutputStream; |
40 | using grpc::protobuf::io::ZeroCopyOutputStream; |
41 | using grpc_generator::StringReplace; |
42 | using grpc_generator::StripProto; |
43 | using std::vector; |
44 | |
45 | namespace grpc_python_generator { |
46 | |
47 | namespace { |
48 | |
49 | typedef vector<const Descriptor*> DescriptorVector; |
50 | typedef vector<grpc::string> StringVector; |
51 | |
52 | static grpc::string StripModulePrefixes( |
53 | const grpc::string& raw_module_name, |
54 | const std::vector<grpc::string>& prefixes_to_filter) { |
55 | for (const auto& prefix : prefixes_to_filter) { |
56 | if (raw_module_name.rfind(prefix, 0) == 0) { |
57 | return raw_module_name.substr(prefix.size(), |
58 | raw_module_name.size() - prefix.size()); |
59 | } |
60 | } |
61 | return raw_module_name; |
62 | } |
63 | |
64 | // TODO(https://github.com/google/protobuf/issues/888): |
65 | // Export `ModuleName` from protobuf's |
66 | // `src/google/protobuf/compiler/python/python_generator.cc` file. |
67 | grpc::string ModuleName(const grpc::string& filename, |
68 | const grpc::string& import_prefix, |
69 | const std::vector<grpc::string>& prefixes_to_filter) { |
70 | grpc::string basename = StripProto(filename); |
71 | basename = StringReplace(basename, "-" , "_" ); |
72 | basename = StringReplace(basename, "/" , "." ); |
73 | return StripModulePrefixes(import_prefix + basename + "_pb2" , |
74 | prefixes_to_filter); |
75 | } |
76 | |
77 | // TODO(https://github.com/google/protobuf/issues/888): |
78 | // Export `ModuleAlias` from protobuf's |
79 | // `src/google/protobuf/compiler/python/python_generator.cc` file. |
80 | grpc::string ModuleAlias(const grpc::string& filename, |
81 | const grpc::string& import_prefix, |
82 | const std::vector<grpc::string>& prefixes_to_filter) { |
83 | grpc::string module_name = |
84 | ModuleName(filename, import_prefix, prefixes_to_filter); |
85 | // We can't have dots in the module name, so we replace each with _dot_. |
86 | // But that could lead to a collision between a.b and a_dot_b, so we also |
87 | // duplicate each underscore. |
88 | module_name = StringReplace(module_name, "_" , "__" ); |
89 | module_name = StringReplace(module_name, "." , "_dot_" ); |
90 | return module_name; |
91 | } |
92 | |
93 | bool GetModuleAndMessagePath( |
94 | const Descriptor* type, grpc::string* out, grpc::string generator_file_name, |
95 | bool generate_in_pb2_grpc, grpc::string& import_prefix, |
96 | const std::vector<grpc::string>& prefixes_to_filter) { |
97 | const Descriptor* path_elem_type = type; |
98 | DescriptorVector message_path; |
99 | do { |
100 | message_path.push_back(path_elem_type); |
101 | path_elem_type = path_elem_type->containing_type(); |
102 | } while (path_elem_type); // implicit nullptr comparison; don't be explicit |
103 | grpc::string file_name = type->file()->name(); |
104 | static const int proto_suffix_length = strlen(".proto" ); |
105 | if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) && |
106 | file_name.find_last_of(".proto" ) == file_name.size() - 1)) { |
107 | return false; |
108 | } |
109 | |
110 | grpc::string module; |
111 | if (generator_file_name != file_name || generate_in_pb2_grpc) { |
112 | module = ModuleAlias(file_name, import_prefix, prefixes_to_filter) + "." ; |
113 | } else { |
114 | module = "" ; |
115 | } |
116 | grpc::string message_type; |
117 | for (DescriptorVector::reverse_iterator path_iter = message_path.rbegin(); |
118 | path_iter != message_path.rend(); ++path_iter) { |
119 | message_type += (*path_iter)->name() + "." ; |
120 | } |
121 | // no pop_back prior to C++11 |
122 | message_type.resize(message_type.size() - 1); |
123 | *out = module + message_type; |
124 | return true; |
125 | } |
126 | |
127 | template <typename DescriptorType> |
128 | StringVector (const DescriptorType* descriptor) { |
129 | StringVector ; |
130 | grpc_generator::GetComment( |
131 | descriptor, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &comments); |
132 | grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_LEADING, |
133 | &comments); |
134 | grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_TRAILING, |
135 | &comments); |
136 | return comments; |
137 | } |
138 | |
139 | inline void Split(const grpc::string& s, char delim, |
140 | std::vector<grpc::string>* append_to) { |
141 | auto current = s.begin(); |
142 | while (current <= s.end()) { |
143 | auto next = std::find(current, s.end(), delim); |
144 | append_to->emplace_back(current, next); |
145 | current = next + 1; |
146 | } |
147 | } |
148 | |
149 | } // namespace |
150 | |
151 | } // namespace grpc_python_generator |
152 | |
153 | #endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H |
154 | |