Apollo 10.0
自动驾驶开放平台
message_traits.h
浏览该文件的文档.
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
17#ifndef CYBER_MESSAGE_MESSAGE_TRAITS_H_
18#define CYBER_MESSAGE_MESSAGE_TRAITS_H_
19
20#include <string>
21#include <typeinfo>
22
23#include "cyber/base/macros.h"
24#include "cyber/common/log.h"
30
31namespace apollo {
32namespace cyber {
33namespace message {
34
35DEFINE_TYPE_TRAIT(HasByteSize, ByteSizeLong)
36DEFINE_TYPE_TRAIT(HasType, TypeName)
38DEFINE_TYPE_TRAIT(HasGetDescriptorString, GetDescriptorString)
39DEFINE_TYPE_TRAIT(HasDescriptor, descriptor)
40DEFINE_TYPE_TRAIT(HasFullName, full_name)
41DEFINE_TYPE_TRAIT(HasSerializeToString, SerializeToString)
42DEFINE_TYPE_TRAIT(HasParseFromString, ParseFromString)
43DEFINE_TYPE_TRAIT(HasSerializeToArray, SerializeToArray)
44DEFINE_TYPE_TRAIT(HasParseFromArray, ParseFromArray)
45DEFINE_TYPE_TRAIT(HasSerializeToArenaMessageWrapper,
47DEFINE_TYPE_TRAIT(HasParseFromArenaMessageWrapper, ParseFromArenaMessageWrapper)
48
49template <typename T>
50class HasSerializer {
51 public:
52 static constexpr bool value =
53 HasSerializeToString<T>::value && HasParseFromString<T>::value &&
54 HasSerializeToArray<T>::value && HasParseFromArray<T>::value;
55};
56
57// avoid potential ODR violation
58template <typename T>
59constexpr bool HasSerializer<T>::value;
60
61template <typename T,
62 typename std::enable_if<HasType<T>::value &&
63 std::is_member_function_pointer<
64 decltype(&T::TypeName)>::value,
65 bool>::type = 0>
66std::string MessageType(const T& message) {
67 return message.TypeName();
68}
69
70template <typename T,
71 typename std::enable_if<HasType<T>::value &&
72 !std::is_member_function_pointer<
73 decltype(&T::TypeName)>::value,
74 bool>::type = 0>
75std::string MessageType(const T& message) {
76 return T::TypeName();
77}
78
79template <typename T,
80 typename std::enable_if<
81 !HasType<T>::value &&
82 !std::is_base_of<google::protobuf::Message, T>::value,
83 bool>::type = 0>
84std::string MessageType(const T& message) {
85 return typeid(T).name();
86}
87
88template <typename T,
89 typename std::enable_if<HasType<T>::value &&
90 !std::is_member_function_pointer<
91 decltype(&T::TypeName)>::value,
92 bool>::type = 0>
93std::string MessageType() {
94 return T::TypeName();
95}
96
97template <typename T,
98 typename std::enable_if<
99 !HasType<T>::value &&
100 !std::is_base_of<google::protobuf::Message, T>::value,
101 bool>::type = 0>
102std::string MessageType() {
103 return typeid(T).name();
104}
105
106template <
107 typename T,
108 typename std::enable_if<
109 HasType<T>::value &&
110 std::is_member_function_pointer<decltype(&T::TypeName)>::value &&
111 !std::is_base_of<google::protobuf::Message, T>::value,
112 bool>::type = 0>
113std::string MessageType() {
114 return typeid(T).name();
115}
116
117template <typename T>
118typename std::enable_if<HasSetType<T>::value, void>::type SetTypeName(
119 const std::string& type_name, T* message) {
120 message->SetTypeName(type_name);
121}
122
123template <typename T>
124typename std::enable_if<!HasSetType<T>::value, void>::type SetTypeName(
125 const std::string& type_name, T* message) {}
126
127template <typename T>
128typename std::enable_if<HasByteSize<T>::value, int>::type ByteSize(
129 const T& message) {
130 return static_cast<int>(message.ByteSizeLong());
131}
132
133template <typename T>
134typename std::enable_if<!HasByteSize<T>::value, int>::type ByteSize(
135 const T& message) {
136 (void)message;
137 return -1;
138}
139
140template <typename T>
141int FullByteSize(const T& message) {
142 int content_size = ByteSize(message);
143 if (content_size < 0) {
144 return content_size;
145 }
146 return content_size + static_cast<int>(sizeof(MessageHeader));
147}
148
149template <typename T>
150typename std::enable_if<HasParseFromArenaMessageWrapper<T>::value, bool>::type
152 T** message_ptr) {
153 return message->ParseFromArenaMessageWrapper(wrapper, message_ptr);
154}
155
156template <typename T,
157 typename std::enable_if<
158 !HasParseFromArenaMessageWrapper<T>::value &&
159 !std::is_base_of<google::protobuf::Message, T>::value,
160 bool>::type = 0>
162 T** message_ptr) {
163 (void)wrapper;
164 (void)message;
165 (void)message_ptr;
166 return false;
167}
168
169template <typename T>
170typename std::enable_if<HasParseFromArray<T>::value, bool>::type ParseFromArray(
171 const void* data, int size, T* message) {
172 return message->ParseFromArray(data, size);
173}
174
175template <typename T>
176typename std::enable_if<!HasParseFromArray<T>::value, bool>::type
177ParseFromArray(const void* data, int size, T* message) {
178 return false;
179}
180
181template <typename T>
182typename std::enable_if<HasParseFromString<T>::value, bool>::type
183ParseFromString(const std::string& str, T* message) {
184 return message->ParseFromString(str);
185}
186
187template <typename T>
188typename std::enable_if<!HasParseFromString<T>::value, bool>::type
189ParseFromString(const std::string& str, T* message) {
190 return false;
191}
192
193template <typename T>
194typename std::enable_if<HasParseFromArray<T>::value, bool>::type ParseFromHC(
195 const void* data, int size, T* message) {
196 const auto header_size = sizeof(MessageHeader);
197 RETURN_VAL_IF(size < (int)header_size, false);
198 const MessageHeader* header = static_cast<const MessageHeader*>(data);
199 RETURN_VAL_IF((size - header_size) < header->content_size(), false);
200 SetTypeName(header->msg_type(), message);
201 return message->ParseFromArray(
202 static_cast<const void*>(static_cast<const char*>(data) + header_size),
203 header->content_size());
204}
205
206template <typename T>
207typename std::enable_if<!HasParseFromArray<T>::value, bool>::type ParseFromHC(
208 const void* data, int size, T* message) {
209 return false;
210}
211
212template <typename T>
213typename std::enable_if<HasSerializeToArenaMessageWrapper<T>::value, bool>::type
215 T** message_ptr) {
216 return message->SerializeToArenaMessageWrapper(wrapper, message_ptr);
217}
218
219template <typename T,
220 typename std::enable_if<
221 !HasSerializeToArenaMessageWrapper<T>::value &&
222 !std::is_base_of<google::protobuf::Message, T>::value,
223 bool>::type = 0>
224bool SerializeToArenaMessageWrapper(const T& message,
225 ArenaMessageWrapper* wrapper,
226 T** message_ptr) {
227 (void)message;
228 (void)wrapper;
229 (void)message_ptr;
230 return false;
231}
232
233template <typename T>
234typename std::enable_if<HasSerializeToArray<T>::value, bool>::type
235SerializeToArray(const T& message, void* data, int size) {
236 return message.SerializeToArray(data, size);
237}
238
239template <typename T>
240typename std::enable_if<!HasSerializeToArray<T>::value, bool>::type
241SerializeToArray(const T& message, void* data, int size) {
242 return false;
243}
244
245template <typename T>
246typename std::enable_if<HasSerializeToString<T>::value, bool>::type
247SerializeToString(const T& message, std::string* str) {
248 return message.SerializeToString(str);
249}
250
251template <typename T>
252typename std::enable_if<!HasSerializeToString<T>::value, bool>::type
253SerializeToString(const T& message, std::string* str) {
254 return false;
255}
256
257template <typename T>
258typename std::enable_if<HasSerializeToArray<T>::value, bool>::type
259SerializeToHC(const T& message, void* data, int size) {
260 int msg_size = ByteSize(message);
261 if (msg_size < 0) {
262 return false;
263 }
264 const std::string& type_name = MessageType(message);
265 MessageHeader header;
266 header.set_msg_type(type_name.data(), type_name.size());
267 header.set_content_size(msg_size);
268 if (sizeof(header) > static_cast<size_t>(size)) {
269 return false;
270 }
271 char* ptr = reinterpret_cast<char*>(data);
272 memcpy(ptr, static_cast<const void*>(&header), sizeof(header));
273 ptr += sizeof(header);
274 int left_size = size - static_cast<int>(sizeof(header));
275 return SerializeToArray(message, reinterpret_cast<void*>(ptr), left_size);
276}
277
278template <typename T>
279typename std::enable_if<!HasSerializeToArray<T>::value, bool>::type
280SerializeToHC(const T& message, void* data, int size) {
281 return false;
282}
283
284template <typename T, typename std::enable_if<HasGetDescriptorString<T>::value,
285 bool>::type = 0>
286void GetDescriptorString(const std::string& type, std::string* desc_str) {
287 T::GetDescriptorString(type, desc_str);
288}
289
290template <typename T,
291 typename std::enable_if<
292 !HasGetDescriptorString<T>::value &&
293 !std::is_base_of<google::protobuf::Message, T>::value,
294 bool>::type = 0>
295void GetDescriptorString(const std::string& type, std::string* desc_str) {}
296
297template <typename MessageT,
298 typename std::enable_if<
299 !std::is_base_of<google::protobuf::Message, MessageT>::value,
300 int>::type = 0>
301void GetDescriptorString(const MessageT& message, std::string* desc_str) {}
302
303template <
304 typename T, typename Descriptor,
305 typename std::enable_if<HasFullName<Descriptor>::value, bool>::type = 0>
306std::string GetFullName() {
307 return T::descriptor()->full_name();
308}
309
310template <
311 typename T, typename Descriptor,
312 typename std::enable_if<!HasFullName<Descriptor>::value, bool>::type = 0>
313std::string GetFullName() {
314 return typeid(T).name();
315}
316
317template <typename T,
318 typename std::enable_if<
319 HasDescriptor<T>::value &&
320 !std::is_base_of<google::protobuf::Message, T>::value,
321 bool>::type = 0>
322std::string GetMessageName() {
323 return GetFullName<T, decltype(*T::descriptor())>();
324}
325
326template <typename T,
327 typename std::enable_if<
328 HasDescriptor<T>::value &&
329 std::is_base_of<google::protobuf::Message, T>::value,
330 bool>::type = 0>
331std::string GetMessageName() {
332 return T::descriptor()->full_name();
333}
334
335template <typename T,
336 typename std::enable_if<!HasDescriptor<T>::value, bool>::type = 0>
337std::string GetMessageName() {
338 return typeid(T).name();
339}
340
341} // namespace message
342} // namespace cyber
343} // namespace apollo
344
345#endif // CYBER_MESSAGE_MESSAGE_TRAITS_H_
void set_msg_type(const char *msg_type, size_t msg_type_len)
void set_content_size(uint32_t content_size)
#define DEFINE_TYPE_TRAIT(name, func)
Definition macros.h:35
#define RETURN_VAL_IF(condition, val)
Definition log.h:114
std::enable_if< HasSerializeToArray< T >::value, bool >::type SerializeToArray(const T &message, void *data, int size)
std::enable_if< HasParseFromArenaMessageWrapper< T >::value, bool >::type ParseFromArenaMessageWrapper(ArenaMessageWrapper *wrapper, T *message, T **message_ptr)
std::enable_if< HasSetType< T >::value, void >::type SetTypeName(const std::string &type_name, T *message)
std::enable_if< HasSerializeToString< T >::value, bool >::type SerializeToString(const T &message, std::string *str)
std::enable_if< HasByteSize< T >::value, int >::type ByteSize(const T &message)
std::enable_if< HasParseFromString< T >::value, bool >::type ParseFromString(const std::string &str, T *message)
std::string GetMessageName()
std::enable_if< HasSerializeToArenaMessageWrapper< T >::value, bool >::type SerializeToArenaMessageWrapper(const T &message, ArenaMessageWrapper *wrapper, T **message_ptr)
std::enable_if< HasParseFromArray< T >::value, bool >::type ParseFromArray(const void *data, int size, T *message)
std::string MessageType()
std::enable_if< HasSerializeToArray< T >::value, bool >::type SerializeToHC(const T &message, void *data, int size)
int FullByteSize(const T &message)
void GetDescriptorString(const std::string &type, std::string *desc_str)
std::enable_if< HasParseFromArray< T >::value, bool >::type ParseFromHC(const void *data, int size, T *message)
class register implement
Definition arena_queue.h:37