YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/gen_yrpc/model.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include "yb/gen_yrpc/model.h"
15
16
#include <boost/algorithm/string/predicate.hpp>
17
18
#include <google/protobuf/descriptor.h>
19
#include <google/protobuf/descriptor.pb.h>
20
21
#include "yb/gutil/macros.h"
22
#include "yb/gutil/strings/join.h"
23
#include "yb/gutil/strings/split.h"
24
25
#include "yb/rpc/service.pb.h"
26
27
using google::protobuf::internal::WireFormatLite;
28
29
namespace yb {
30
namespace gen_yrpc {
31
32
namespace {
33
34
const std::string kProtoExtension = ".proto";
35
36
}
37
38
0
WireFormatLite::FieldType FieldType(const google::protobuf::FieldDescriptor* field) {
39
0
  return static_cast<WireFormatLite::FieldType>(field->type());
40
0
}
41
42
0
WireFormatLite::WireType WireType(const google::protobuf::FieldDescriptor* field) {
43
0
  return WireFormatLite::WireTypeForFieldType(FieldType(field));
44
0
}
45
46
0
size_t FixedSize(const google::protobuf::FieldDescriptor* field) {
47
0
  switch (FieldType(field)) {
48
0
    case WireFormatLite::TYPE_DOUBLE: FALLTHROUGH_INTENDED;
49
0
    case WireFormatLite::TYPE_FIXED64: FALLTHROUGH_INTENDED;
50
0
    case WireFormatLite::TYPE_SFIXED64:
51
0
      return 8;
52
0
    case WireFormatLite::TYPE_FLOAT: FALLTHROUGH_INTENDED;
53
0
    case WireFormatLite::TYPE_FIXED32: FALLTHROUGH_INTENDED;
54
0
    case WireFormatLite::TYPE_SFIXED32:
55
0
      return 4;
56
0
    case WireFormatLite::TYPE_BOOL:
57
0
      return 1;
58
0
    case WireFormatLite::TYPE_INT64: FALLTHROUGH_INTENDED;
59
0
    case WireFormatLite::TYPE_UINT64: FALLTHROUGH_INTENDED;
60
0
    case WireFormatLite::TYPE_INT32: FALLTHROUGH_INTENDED;
61
0
    case WireFormatLite::TYPE_STRING: FALLTHROUGH_INTENDED;
62
0
    case WireFormatLite::TYPE_BYTES: FALLTHROUGH_INTENDED;
63
0
    case WireFormatLite::TYPE_UINT32: FALLTHROUGH_INTENDED;
64
0
    case WireFormatLite::TYPE_ENUM: FALLTHROUGH_INTENDED;
65
0
    case WireFormatLite::TYPE_SINT32: FALLTHROUGH_INTENDED;
66
0
    case WireFormatLite::TYPE_SINT64: FALLTHROUGH_INTENDED;
67
0
    case WireFormatLite::TYPE_MESSAGE: FALLTHROUGH_INTENDED;
68
0
    case WireFormatLite::TYPE_GROUP: FALLTHROUGH_INTENDED;
69
0
    default:
70
0
      return 0;
71
0
  }
72
0
}
73
74
0
std::string MakeLightweightName(const std::string& input) {
75
0
  auto idx = input.find_last_of('.');
76
0
  if (idx != std::string::npos) {
77
0
    ++idx;
78
0
  } else {
79
0
    idx = 0;
80
0
  }
81
0
  return input.substr(0, idx) + "LW" + input.substr(idx);
82
0
}
83
84
0
bool IsLightweightMethod(const google::protobuf::MethodDescriptor* method, rpc::RpcSides side) {
85
0
  const auto& options = method->options().GetExtension(rpc::lightweight_method);
86
0
  if (side == rpc::RpcSides::BOTH) {
87
0
    return options.sides() != rpc::RpcSides::NONE;
88
0
  }
89
0
  return options.sides() == side || options.sides() == rpc::RpcSides::BOTH;
90
0
}
91
92
0
bool IsTrivialMethod(const google::protobuf::MethodDescriptor* method) {
93
0
  return method->options().GetExtension(rpc::trivial);
94
0
}
95
96
0
bool HasLightweightMethod(const google::protobuf::ServiceDescriptor* service, rpc::RpcSides side) {
97
0
  for (int i = 0; i != service->method_count(); ++i) {
98
0
    if (IsLightweightMethod(service->method(i), side)) {
99
0
      return true;
100
0
    }
101
0
  }
102
0
  return false;
103
0
}
104
105
0
bool HasLightweightMethod(const google::protobuf::FileDescriptor* file, rpc::RpcSides side) {
106
0
  for (int i = 0; i != file->service_count(); ++i) {
107
0
    if (HasLightweightMethod(file->service(i), side)) {
108
0
      return true;
109
0
    }
110
0
  }
111
112
0
  return false;
113
0
}
114
115
0
std::string ReplaceNamespaceDelimiters(const std::string& arg_full_name) {
116
0
  return JoinStrings(strings::Split(arg_full_name, "."), "::");
117
0
}
118
119
// Strips the package from method arguments if they are in the same package as
120
// the service, otherwise leaves them so that we can have fully qualified
121
// namespaces for method arguments.
122
0
std::string RelativeClassPath(const std::string& clazz, const std::string& service) {
123
0
  GStringPiece service_package(service);
124
0
  auto last_dot = service_package.rfind('.');
125
0
  if (last_dot != GStringPiece::npos) {
126
0
    service_package = service_package.substr(0, last_dot + 1);
127
128
0
    GStringPiece clazz_path(clazz);
129
0
    if (clazz_path.starts_with(service_package)) {
130
0
      return ReplaceNamespaceDelimiters(clazz_path.substr(service_package.length()).ToString());
131
0
    }
132
0
  }
133
134
0
  return "::" + ReplaceNamespaceDelimiters(clazz);
135
0
}
136
137
std::string UnnestedName(
138
0
    const google::protobuf::Descriptor* message, Lightweight lightweight, bool full_path) {
139
0
  auto name = lightweight ? MakeLightweightName(message->name()) : message->name();
140
0
  if (message->options().map_entry()) {
141
0
    name += "_DoNotUse";
142
0
  }
143
0
  if (message->containing_type()) {
144
0
    return UnnestedName(message->containing_type(), lightweight, full_path) + "_" + name;
145
0
  }
146
0
  if (full_path) {
147
0
    const auto& full_name = message->full_name();
148
0
    auto idx = full_name.find_last_of('.');
149
0
    if (idx != std::string::npos) {
150
0
      return full_name.substr(0, idx + 1) + name;
151
0
    }
152
0
  }
153
0
  return name;
154
0
}
155
156
0
std::string MapFieldType(const google::protobuf::FieldDescriptor* field, Lightweight lightweight) {
157
0
  switch (WireFormatLite::FieldTypeToCppType(FieldType(field))) {
158
0
    case WireFormatLite::CppType::CPPTYPE_INT32:
159
0
      return "int32_t";
160
0
    case WireFormatLite::CppType::CPPTYPE_INT64:
161
0
      return "int64_t";
162
0
    case WireFormatLite::CppType::CPPTYPE_UINT32:
163
0
      return "uint32_t";
164
0
    case WireFormatLite::CppType::CPPTYPE_UINT64:
165
0
      return "uint64_t";
166
0
    case WireFormatLite::CppType::CPPTYPE_DOUBLE:
167
0
      return "double";
168
0
    case WireFormatLite::CppType::CPPTYPE_FLOAT:
169
0
      return "float";
170
0
    case WireFormatLite::CppType::CPPTYPE_BOOL:
171
0
      return "bool";
172
0
    case WireFormatLite::CppType::CPPTYPE_ENUM:
173
0
      return RelativeClassPath(
174
0
          field->enum_type()->containing_type()
175
0
              ? UnnestedName(field->enum_type()->containing_type(), lightweight, true) + "." +
176
0
                    field->enum_type()->name()
177
0
              : field->enum_type()->full_name(),
178
0
          field->containing_type()->full_name());
179
0
    case WireFormatLite::CppType::CPPTYPE_STRING:
180
0
      return lightweight ? "::yb::Slice" : "std::string";
181
0
    case WireFormatLite::CppType::CPPTYPE_MESSAGE:
182
0
      if (IsPbAny(field->message_type()) && lightweight) {
183
0
        return "::yb::rpc::LWAny";
184
0
      }
185
0
      return RelativeClassPath(UnnestedName(field->message_type(), lightweight, true),
186
0
                               field->containing_type()->full_name());
187
0
    default:
188
0
      break;
189
0
  }
190
0
  return "UNSUPPORTED TYPE";
191
0
}
192
193
0
bool IsMessage(const google::protobuf::FieldDescriptor* field) {
194
0
  return field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE;
195
0
}
196
197
0
bool IsSimple(const google::protobuf::FieldDescriptor* field) {
198
0
  return !field->is_repeated() && !IsMessage(field);
199
0
}
200
201
0
bool NeedArena(const google::protobuf::Descriptor* message) {
202
0
  const auto& options = message->options().GetExtension(rpc::lightweight_message);
203
0
  if (options.force_arena()) {
204
0
    return true;
205
0
  }
206
0
  for (int i = 0; i != message->field_count(); ++i) {
207
0
    const auto* field = message->field(i);
208
0
    if (IsMessage(field) || StoredAsSlice(field)) {
209
0
      return true;
210
0
    }
211
0
  }
212
0
  return false;
213
0
}
214
215
0
bool IsPointerField(const google::protobuf::FieldDescriptor* field) {
216
0
  const auto& lightweight_field_options = field->options().GetExtension(rpc::lightweight_field);
217
0
  return lightweight_field_options.pointer();
218
0
}
219
220
0
bool StoredAsSlice(const google::protobuf::FieldDescriptor* field) {
221
0
  auto type = field->type();
222
0
  return type == google::protobuf::FieldDescriptor::TYPE_BYTES ||
223
0
         type == google::protobuf::FieldDescriptor::TYPE_STRING;
224
0
}
225
226
0
bool IsPbAny(const google::protobuf::Descriptor* message) {
227
0
  return message->full_name() == "google.protobuf.Any";
228
0
}
229
230
0
bool IsLwAny(const google::protobuf::Descriptor* message) {
231
0
  return message->full_name() == "yb.rpc.Any";
232
0
}
233
234
0
std::string RemoveProtoExtension(const std::string& fname) {
235
0
  if (boost::ends_with(fname, kProtoExtension)) {
236
0
    return fname.substr(0, fname.length() - kProtoExtension.length());
237
0
  } else {
238
0
    return fname;
239
0
  }
240
0
}
241
242
0
std::vector<std::string> ListDependencies(const google::protobuf::FileDescriptor* file) {
243
0
  std::vector<std::string> result;
244
0
  for (int i = 0; i != file->dependency_count(); ++i) {
245
0
    std::string dependency_path = RemoveProtoExtension(file->dependency(i)->name());
246
0
    if (dependency_path == "google/protobuf/any") {
247
0
      result.push_back("yb/rpc/any");
248
0
      continue;
249
0
    }
250
0
    if (dependency_path == "yb/rpc/rpc_header" ||
251
0
        dependency_path == "yb/rpc/lightweight_message" ||
252
0
        dependency_path == "yb/rpc/service" ||
253
0
        boost::starts_with(dependency_path, "google/protobuf/")) {
254
0
      continue;
255
0
    }
256
0
    result.push_back(std::move(dependency_path));
257
0
  }
258
0
  return result;
259
0
}
260
261
} // namespace gen_yrpc
262
} // namespace yb