Apollo 10.0
自动驾驶开放平台
protobuf_factory.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 *****************************************************************************/
16
18
19#include "cyber/common/log.h"
20
21namespace apollo {
22namespace cyber {
23namespace message {
24
25using google::protobuf::MessageFactory;
26
27ProtobufFactory::ProtobufFactory() {
28 pool_.reset(new DescriptorPool());
29 factory_.reset(new DynamicMessageFactory(pool_.get()));
30}
31
33 factory_.reset();
34 pool_.reset();
35}
36
38 const google::protobuf::Message& message) {
39 const Descriptor* descriptor = message.GetDescriptor();
40 return RegisterMessage(*descriptor);
41}
42
43bool ProtobufFactory::RegisterMessage(const Descriptor& desc) {
44 FileDescriptorProto file_desc_proto;
45 desc.file()->CopyTo(&file_desc_proto);
46 return RegisterMessage(file_desc_proto);
47}
48
49bool ProtobufFactory::RegisterMessage(const ProtoDesc& proto_desc) {
50 FileDescriptorProto file_desc_proto;
51 file_desc_proto.ParseFromString(proto_desc.desc());
52
53 // If the message in this proto file has been registered, return true.
54 if (FindMessageTypeByFile(file_desc_proto)) {
55 return true;
56 }
57 for (int i = 0; i < proto_desc.dependencies_size(); ++i) {
58 auto dep = proto_desc.dependencies(i);
59 if (!RegisterMessage(dep)) {
60 return false;
61 }
62 FileDescriptorProto dep_file_desc_proto;
63 dep_file_desc_proto.ParseFromString(dep.desc());
64 const google::protobuf::Descriptor* descriptor =
65 FindMessageTypeByFile(dep_file_desc_proto);
66
67 // If descriptor is found, replace the dependency with registered path.
68 if (descriptor != nullptr) {
69 file_desc_proto.set_dependency(i, descriptor->file()->name());
70 }
71 }
72 return RegisterMessage(file_desc_proto);
73}
74
75bool ProtobufFactory::RegisterPythonMessage(const std::string& proto_str) {
76 FileDescriptorProto file_desc_proto;
77 file_desc_proto.ParseFromString(proto_str);
78 return RegisterMessage(file_desc_proto);
79}
80
81bool ProtobufFactory::RegisterMessage(const std::string& proto_desc_str) {
82 ProtoDesc proto_desc;
83 proto_desc.ParseFromString(proto_desc_str);
84 return RegisterMessage(proto_desc);
85}
86
87// Internal method
89 const FileDescriptorProto& file_desc_proto) {
91 std::lock_guard<std::mutex> lg(register_mutex_);
92 auto file_desc = pool_->BuildFileCollectingErrors(file_desc_proto, &ec);
93 if (!file_desc) {
94 /*
95 AERROR << "Failed to register protobuf messages ["
96 << file_desc_proto.name() << "]";
97 */
98 return false;
99 }
100 return true;
101}
102
103// Internal method
104bool ProtobufFactory::GetProtoDesc(const FileDescriptor* file_desc,
105 ProtoDesc* proto_desc) {
106 FileDescriptorProto file_desc_proto;
107 file_desc->CopyTo(&file_desc_proto);
108 std::string str("");
109 if (!file_desc_proto.SerializeToString(&str)) {
110 return false;
111 }
112
113 proto_desc->set_desc(str);
114
115 for (int i = 0; i < file_desc->dependency_count(); ++i) {
116 auto desc = proto_desc->add_dependencies();
117 if (!GetProtoDesc(file_desc->dependency(i), desc)) {
118 return false;
119 }
120 }
121
122 return true;
123}
124
125void ProtobufFactory::GetDescriptorString(const Descriptor* desc,
126 std::string* desc_str) {
127 ProtoDesc proto_desc;
128 if (!GetProtoDesc(desc->file(), &proto_desc)) {
129 AERROR << "Failed to get descriptor from message";
130 return;
131 }
132
133 if (!proto_desc.SerializeToString(desc_str)) {
134 AERROR << "Failed to get descriptor from message";
135 }
136}
137
139 const google::protobuf::Message& message, std::string* desc_str) {
140 const Descriptor* desc = message.GetDescriptor();
141 return GetDescriptorString(desc, desc_str);
142}
143
144void ProtobufFactory::GetPythonDesc(const std::string& type,
145 std::string* desc_str) {
146 auto desc = pool_->FindMessageTypeByName(type);
147 if (desc == nullptr) {
148 return;
149 }
150 google::protobuf::DescriptorProto dp;
151 desc->CopyTo(&dp);
152 dp.SerializeToString(desc_str);
153}
154
155void ProtobufFactory::GetDescriptorString(const std::string& type,
156 std::string* desc_str) {
157 auto desc = DescriptorPool::generated_pool()->FindMessageTypeByName(type);
158 if (desc != nullptr) {
159 return GetDescriptorString(desc, desc_str);
160 }
161
162 desc = pool_->FindMessageTypeByName(type);
163 if (desc == nullptr) {
164 return;
165 }
166 return GetDescriptorString(desc, desc_str);
167}
168
169void ProtobufFactory::GetProtoPath(const std::string& type,
170 std::string& location) {
171 auto desc = DescriptorPool::generated_pool()->FindMessageTypeByName(type);
172 if (desc != nullptr) {
173 location = (desc->file())->name();
174 return;
175 }
176
177 desc = pool_->FindMessageTypeByName(type);
178 if (desc == nullptr) {
179 return;
180 }
181 location = (desc->file())->name();
182 return;
183}
184
185// Internal method
186google::protobuf::Message* ProtobufFactory::GenerateMessageByType(
187 const std::string& type) const {
188 google::protobuf::Message* message = GetMessageByGeneratedType(type);
189 if (message != nullptr) {
190 return message;
191 }
192
193 const google::protobuf::Descriptor* descriptor =
194 pool_->FindMessageTypeByName(type);
195 if (descriptor == nullptr) {
196 AERROR << "cannot find [" << type << "] descriptor";
197 return nullptr;
198 }
199
200 const google::protobuf::Message* prototype =
201 factory_->GetPrototype(descriptor);
202 if (prototype == nullptr) {
203 AERROR << "cannot find [" << type << "] prototype";
204 return nullptr;
205 }
206
207 return prototype->New();
208}
209
210google::protobuf::Message* ProtobufFactory::GetMessageByGeneratedType(
211 const std::string& type) const {
212 auto descriptor =
213 DescriptorPool::generated_pool()->FindMessageTypeByName(type);
214 if (descriptor == nullptr) {
215 // AERROR << "cannot find [" << type << "] descriptor";
216 return nullptr;
217 }
218
219 auto prototype =
220 MessageFactory::generated_factory()->GetPrototype(descriptor);
221 if (prototype == nullptr) {
222 // AERROR << "cannot find [" << type << "] prototype";
223 return nullptr;
224 }
225
226 return prototype->New();
227}
228
230 const std::string& name) const {
231 return pool_->FindMessageTypeByName(name);
232}
233
234const google::protobuf::ServiceDescriptor* ProtobufFactory::FindServiceByName(
235 const std::string& name) const {
236 return pool_->FindServiceByName(name);
237}
238
240 const FileDescriptorProto& file_desc_proto) {
241 const std::string& scope = file_desc_proto.package();
242 std::string type;
243 if (file_desc_proto.message_type_size()) {
244 type = scope + "." + file_desc_proto.message_type(0).name();
245 }
246 const google::protobuf::Descriptor* descriptor =
247 pool_->FindMessageTypeByName(type);
248 return descriptor;
249}
250
251void ErrorCollector::AddError(const std::string& filename,
252 const std::string& element_name,
253 const google::protobuf::Message* descriptor,
254 ErrorLocation location,
255 const std::string& message) {
256 UNUSED(element_name);
257 UNUSED(descriptor);
258 UNUSED(location);
259 AWARN << "[" << filename << "] " << message;
260}
261
262void ErrorCollector::AddWarning(const std::string& filename,
263 const std::string& element_name,
264 const google::protobuf::Message* descriptor,
265 ErrorLocation location,
266 const std::string& message) {
267 UNUSED(element_name);
268 UNUSED(descriptor);
269 UNUSED(location);
270 AWARN << "[" << filename << "] " << message;
271}
272
273} // namespace message
274} // namespace cyber
275} // namespace apollo
const google::protobuf::ServiceDescriptor * FindServiceByName(const std::string &name) const
bool RegisterMessage(const std::string &proto_desc_str)
const Descriptor * FindMessageTypeByName(const std::string &type) const
const Descriptor * FindMessageTypeByFile(const FileDescriptorProto &file_desc_proto)
bool RegisterPythonMessage(const std::string &proto_str)
void GetPythonDesc(const std::string &type, std::string *desc_str)
void GetProtoPath(const std::string &type, std::string &location)
static void GetDescriptorString(const google::protobuf::Message &message, std::string *desc_str)
google::protobuf::Message * GenerateMessageByType(const std::string &type) const
#define UNUSED(param)
Definition macros.h:46
#define AERROR
Definition log.h:44
#define AWARN
Definition log.h:43
class register implement
Definition arena_queue.h:37
repeated ProtoDesc dependencies