VLink  2.0.0
A high-performance communication middleware
serializer-inl.h
浏览该文件的文档.
1 /*
2  * Copyright (C) 2026 by Thun Lu. All rights reserved.
3  * Author: Thun Lu <thun.lu@zohomail.cn>
4  * Repo: https://github.com/thun-res/vlink
5  * _ __ __ _ __
6  * | | / / / / (_) ____ / /__
7  * | | / / / / / / / __ \ / //_/
8  * | |/ / / /___ / / / / / / / ,<
9  * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 
24 #pragma once
25 
26 #include <cstring>
27 #include <sstream>
28 #include <string>
29 #include <type_traits>
30 #include <utility>
31 
32 #include "../base/helpers.h"
33 #include "../base/logger.h"
34 #include "../base/name_detector.h"
35 #include "../base/traits.h"
36 #include "../serializer.h"
37 
38 #ifndef VLINK_FASTDDS_IDL_PREFIX
39 #define VLINK_FASTDDS_IDL_PREFIX "dds::"
40 #endif
41 
42 // NOLINTBEGIN
43 
44 #if __has_include(<fastcdr/Cdr.h>)
45 [[maybe_unused]] static constexpr bool kVlinkHasFastcdr = true;
46 
47 #include <fastcdr/Cdr.h>
48 #else
49 #define FASTCDR_VERSION_MAJOR 1
50 [[maybe_unused]] static constexpr bool kVlinkHasFastcdr = false;
51 
52 namespace eprosima::fastcdr {
53 
54 class FastBuffer {
55  public:
56  explicit FastBuffer(char*, size_t) {}
57 };
58 
59 class CdrVersion {
60  public:
61  enum Type {
63  };
64 };
65 
66 class Cdr {
67  public:
68  enum Type {
71  };
72 
73  explicit Cdr(FastBuffer&, int, int) {}
74 };
75 } // namespace eprosima::fastcdr
76 #endif
77 
78 #if __has_include(<google/protobuf/message_lite.h>)
79 [[maybe_unused]] static constexpr bool kVlinkHasProtobuf = true;
80 
81 #include <google/protobuf/message_lite.h>
82 
83 #if __has_include(<google/protobuf/stubs/common.h>)
84 #include <google/protobuf/stubs/common.h>
85 #endif
86 
87 #if __has_include(<google/protobuf/arena.h>)
88 #include <google/protobuf/arena.h>
89 #endif
90 
91 #else
92 
93 #ifndef GOOGLE_PROTOBUF_VERSION
94 #define GOOGLE_PROTOBUF_VERSION 0
95 #endif
96 
97 [[maybe_unused]] static constexpr bool kVlinkHasProtobuf = false;
98 
99 namespace google::protobuf {
100 
101 struct Arena {
102  template <typename T>
103  [[maybe_unused]] static T* Create(Arena*) {
104  return nullptr;
105  }
106 };
107 
108 } // namespace google::protobuf
109 
110 #endif
111 
112 #if __has_include(<flatbuffers/flatbuffers.h>)
113 [[maybe_unused]] static constexpr bool kVlinkHasFlatbuffers = true;
114 
115 #include <flatbuffers/flatbuffers.h>
116 #else
117 [[maybe_unused]] static constexpr bool kVlinkHasFlatbuffers = false;
118 
119 namespace flatbuffers {
120 
121 template <typename ReturnT, typename T>
122 [[maybe_unused]] static const ReturnT* GetRoot(const T&) {
123  return nullptr;
124 }
125 
127  size_t GetSize() const { return 0; }
128 
129  const uint8_t* GetBufferPointer() const { return nullptr; }
130 
131  const uint8_t* GetCurrentBufferPointer() const { return nullptr; }
132 
133  void PushBytes(const uint8_t*, size_t) {}
134 
135  void Finish() const {}
136 };
137 
138 struct Table {};
139 
140 struct NativeTable {};
141 
142 struct Verifier {
143  Verifier(const uint8_t*, size_t) {}
144 
145  template <typename T>
146  bool VerifyBuffer(void*) {
147  return false;
148  }
149 };
150 
151 } // namespace flatbuffers
152 #endif
153 
154 // NOLINTEND
155 
156 namespace vlink {
157 
158 namespace Serializer { // NOLINT(readability-identifier-naming)
159 
160 [[maybe_unused]] inline constexpr bool is_supported(Type type) noexcept { return type != kUnknownType; }
161 
162 template <typename T>
163 inline constexpr Type get_type_of() noexcept {
164  if constexpr (is_bytes_type<T>()) {
165  return kBytesType;
166  } else if constexpr (is_dynamic_type<T>()) {
167  return kDynamicType;
168  } else if constexpr (is_cdr_type<T>()) {
169  return kCdrType;
170  } else if constexpr (is_proto_type<T>()) {
171  return kProtoType;
172  } else if constexpr (is_proto_ptr_type<T>()) {
173  return kProtoPtrType;
174  } else if constexpr (is_flat_table_type<T>()) {
175  return kFlatTableType;
176  } else if constexpr (is_flat_ptr_type<T>()) {
177  return kFlatPtrType;
178  } else if constexpr (is_flat_builder_type<T>()) {
179  return kFlatBuilderType;
180  } else if constexpr (is_custom_type<T>()) {
181  return kCustomType;
182  } else if constexpr (is_string_type<T>()) {
183  return kStringType;
184  } else if constexpr (is_chars_type<T>()) {
185  return kCharsType;
186  } else if constexpr (is_standard_type<T>()) {
187  return kStandardType;
188  } else if constexpr (is_standard_ptr_type<T>()) {
189  return kStandardPtrType;
190  } else if constexpr (is_stream_type<T>()) {
191  return kStreamType;
192  } else {
193  return kUnknownType;
194  }
195 }
196 
197 template <Type TypeT, typename T>
198 inline static constexpr SchemaType get_schema_type() noexcept {
199  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
200 
201  if constexpr (TypeT == kBytesType) {
202  return SchemaType::kRaw;
203  } else if constexpr (TypeT == kCustomType) {
204  if constexpr (VLINK_HAS_MEMBER(RealType, kZerocopyTypes)) {
205  if constexpr (RealType::kZerocopyTypes) {
206  return SchemaType::kZeroCopy;
207  } else {
208  return SchemaType::kRaw;
209  }
210  } else if constexpr (VLINK_HAS_MEMBER(RealType, get_schema_type())) {
211  return RealType::get_schema_type();
212  } else {
213  return SchemaType::kRaw;
214  }
215  } else if constexpr (TypeT == kProtoType || TypeT == kProtoPtrType) {
216  return SchemaType::kProtobuf;
217  } else if constexpr (TypeT == kFlatTableType || TypeT == kFlatPtrType || TypeT == kFlatBuilderType) {
219  } else {
220  return SchemaType::kRaw;
221  }
222 }
223 
224 template <typename T>
225 inline static constexpr SchemaType get_schema_type() noexcept {
226  constexpr auto kType = get_type_of<T>();
227 
228  return get_schema_type<kType, T>();
229 }
230 
231 template <Type TypeT, typename T>
232 inline std::string get_serialized_type() noexcept {
233  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
234  using NamedType = std::remove_pointer_t<RealType>;
235 
236  if constexpr (TypeT == kBytesType) {
237  return "";
238  } else if constexpr (TypeT == kDynamicType) {
239  return "vlink::DynamicData";
240  } else if constexpr (TypeT == kCustomType && VLINK_HAS_MEMBER(RealType, get_serialized_type())) {
242  } else if constexpr (TypeT == kProtoType) {
243 #if GOOGLE_PROTOBUF_VERSION >= 6030000
244  return std::string(RealType{}.GetTypeName());
245 #else
246  return RealType{}.GetTypeName();
247 #endif
248  } else if constexpr (TypeT == kProtoPtrType) {
249 #if GOOGLE_PROTOBUF_VERSION >= 6030000
250  return std::string(std::remove_pointer_t<T>().GetTypeName());
251 #else
252  return std::remove_pointer_t<T>().GetTypeName();
253 #endif
254  } else if constexpr (TypeT == kFlatTableType) {
255  using TableType = typename RealType::TableType;
256  if constexpr (VLINK_HAS_MEMBER(TableType, GetFullyQualifiedName)) {
257  return TableType::GetFullyQualifiedName();
258  } else {
259  std::string name = NameDetector::get<TableType>().data();
260  Helpers::replace_string(name, "::", ".");
261  return name;
262  }
263  } else if constexpr (TypeT == kFlatBuilderType) {
264  using TableType = typename RealType::Table;
265  if constexpr (VLINK_HAS_MEMBER(TableType, GetFullyQualifiedName)) {
266  return TableType::GetFullyQualifiedName();
267  } else {
268  std::string name = NameDetector::get<TableType>().data();
269  Helpers::replace_string(name, "::", ".");
270  return name;
271  }
272  } else if constexpr (TypeT == kFlatPtrType) {
273  using TableType = std::remove_pointer_t<T>;
274  if constexpr (VLINK_HAS_MEMBER(TableType, GetFullyQualifiedName)) {
275  return TableType::GetFullyQualifiedName();
276  } else {
277  std::string name = NameDetector::get<TableType>().data();
278  Helpers::replace_string(name, "::", ".");
279  return name;
280  }
281  } else if constexpr (TypeT == kStringType || TypeT == kCharsType) {
282  return "string";
283  } else if constexpr (NameDetector::is_support<NamedType>()) {
284  return NameDetector::get<NamedType>().data();
285  } else {
286  return "";
287  }
288 }
289 
290 template <typename T>
291 inline std::string get_serialized_type() noexcept {
292  constexpr auto kType = get_type_of<T>();
293 
294  return get_serialized_type<kType, T>();
295 }
296 
297 template <Type TypeT, typename T>
298 inline size_t get_serialized_size(const T& src) noexcept {
299  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
300 
301  if constexpr (TypeT == kBytesType) {
302  return 0;
303  } else if constexpr (TypeT == kDynamicType) {
304  return 0;
305  } else if constexpr (TypeT == kCdrType) {
306  if constexpr (VLINK_HAS_MEMBER(RealType, getCdrSerializedSize(deref(src)))) {
307  return RealType::getCdrSerializedSize(deref(src));
308  } else {
309  return 0;
310  }
311  } else if constexpr (TypeT == kProtoType) {
312  if constexpr (VLINK_HAS_MEMBER(RealType, ByteSizeLong())) {
313  return deref(src).ByteSizeLong();
314  } else {
315  return deref(src).ByteSize();
316  }
317  } else if constexpr (TypeT == kProtoPtrType) {
318  if constexpr (VLINK_HAS_MEMBER(std::remove_pointer_t<T>, ByteSizeLong())) {
319  return src->ByteSizeLong();
320  } else {
321  return src->ByteSize();
322  }
323  } else if constexpr (TypeT == kFlatTableType) {
324  return 0;
325  } else if constexpr (TypeT == kFlatBuilderType) {
326  return src.fbb_.GetSize();
327  } else if constexpr (TypeT == kFlatPtrType) {
328  return 0;
329  } else if constexpr (TypeT == kCustomType) {
330  if constexpr (VLINK_HAS_MEMBER(RealType, get_serialized_size())) {
331  return deref(src).get_serialized_size();
332  } else {
333  return 0;
334  }
335  } else if constexpr (TypeT == kStringType) {
336  return 0;
337  } else if constexpr (TypeT == kCharsType) {
338  return 0;
339  } else if constexpr (TypeT == kStreamType) {
340  return 0;
341  } else if constexpr (TypeT == kStandardType) {
342  return 0;
343  } else if constexpr (TypeT == kStandardPtrType) {
344  return 0;
345  } else {
346  return 0;
347  }
348 }
349 
350 template <typename T>
351 inline size_t get_serialized_size(const T& src) noexcept {
352  constexpr auto kType = get_type_of<T>();
353 
354  return get_serialized_size<kType>(src);
355 }
356 
357 template <Type TypeT, typename T>
358 inline bool serialize(const T& src, Bytes& des, [[maybe_unused]] TransportType transport,
359  [[maybe_unused]] uint8_t offset) {
360  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
361 
362  if constexpr (TypeT == kBytesType) {
363  des = Bytes::deep_copy(src.data(), src.size(), offset);
364  } else if constexpr (TypeT == kDynamicType) {
365  using ReturnT = decltype(deref(src) >> des);
366 
367  if constexpr (std::is_convertible_v<ReturnT, bool>) {
368  if VUNLIKELY (!(deref(src) >> des)) {
369  VLOG_T("Serializer: Dynamic serialize failed.");
370  return false;
371  }
372  } else {
373  deref(src) >> des;
374  }
375  } else if constexpr (TypeT == kCdrType) {
376  if (transport == TransportType::kDds) {
377  des = Bytes::shallow_copy_ptr(&const_cast<RealType&>(deref(src)));
378  } else {
379  if (!des.is_loaned()) {
380  if constexpr (VLINK_HAS_MEMBER(RealType, getCdrSerializedSize(deref(src)))) {
381  size_t target_size = RealType::getCdrSerializedSize(deref(src));
382 
383  if VUNLIKELY (des.size() != target_size) {
384  des = Bytes::create(target_size, offset);
385  }
386  } else {
387  VLOG_W("Serializer: FastBuffer serialize is not supported without dds(v3).");
388  return false;
389  }
390  }
391 
392  eprosima::fastcdr::FastBuffer buffer(reinterpret_cast<char*>(des.data()), des.size());
393 #if FASTCDR_VERSION_MAJOR >= 2
396 #else
398 #endif
399  deref(src).serialize(cdr);
400  }
401  } else if constexpr (TypeT == kProtoType) {
402  if (!des.is_loaned()) {
403  if constexpr (VLINK_HAS_MEMBER(RealType, ByteSizeLong())) {
404  size_t target_size = deref(src).ByteSizeLong();
405 
406  if VUNLIKELY (des.size() != target_size) {
407  des = Bytes::create(target_size, offset);
408  }
409  } else {
410  size_t target_size = deref(src).ByteSize();
411 
412  if VUNLIKELY (des.size() != target_size) {
413  des = Bytes::create(target_size, offset);
414  }
415  }
416  }
417 
418  if VUNLIKELY (!deref(src).SerializeToArray(des.data(), des.size())) {
419  VLOG_T("Serializer: Protobuf serialize failed.");
420  return false;
421  }
422  } else if constexpr (TypeT == kProtoPtrType) {
423  if (!des.is_loaned()) {
424  if constexpr (VLINK_HAS_MEMBER(std::remove_pointer_t<T>, ByteSizeLong())) {
425  size_t target_size = src->ByteSizeLong();
426 
427  if VUNLIKELY (des.size() != target_size) {
428  des = Bytes::create(target_size, offset);
429  }
430  } else {
431  size_t target_size = src->ByteSize();
432 
433  if VUNLIKELY (des.size() != target_size) {
434  des = Bytes::create(target_size, offset);
435  }
436  }
437  }
438 
439  if VUNLIKELY (!src->SerializeToArray(des.data(), des.size())) {
440  VLOG_T("Serializer: Protobuf ptr serialize failed.");
441  return false;
442  }
443  } else if constexpr (TypeT == kFlatTableType) {
445  fbb.Finish(T::TableType::Pack(fbb, &deref(src)));
446 
447  if (des.is_loaned() && des.size() >= fbb.GetSize() + offset) {
448  std::memcpy(des.data() + offset, fbb.GetBufferPointer(), fbb.GetSize());
449  } else {
450  des = Bytes::deep_copy(fbb.GetBufferPointer(), fbb.GetSize(), offset);
451  }
452  } else if constexpr (TypeT == kFlatBuilderType) {
453  src.fbb_.Finish(const_cast<T&>(src).Finish());
454 
455  if (des.is_loaned()) {
456  des = Bytes::shallow_copy(src.fbb_.GetBufferPointer(), src.fbb_.GetSize());
457  } else {
458  des = Bytes::deep_copy(src.fbb_.GetBufferPointer(), src.fbb_.GetSize(), offset);
459  }
460  } else if constexpr (TypeT == kFlatPtrType) {
461  static_assert(Traits::ExpectFalse<T>(), "Not support flat ptr type.");
462  } else if constexpr (TypeT == kCustomType) {
463  using ReturnT = decltype(const_cast<RealType&>(deref(src)) >> des);
464 
465  if constexpr (std::is_convertible_v<ReturnT, bool>) {
466  if VUNLIKELY (!(const_cast<RealType&>(deref(src)) >> des)) {
467  VLOG_T("Serializer: Custom serialize failed.");
468  return false;
469  }
470  } else {
471  const_cast<RealType&>(deref(src)) >> des;
472  }
473 
474  if (offset > 0) {
475  des = Bytes::deep_copy(des.data(), des.size(), offset);
476  }
477  } else if constexpr (TypeT == kStringType) {
478  des = Bytes::deep_copy(reinterpret_cast<const uint8_t*>(deref(src).data()), deref(src).size(), offset);
479  } else if constexpr (TypeT == kCharsType) {
480  des = Bytes::deep_copy(reinterpret_cast<const uint8_t*>(src), std::strlen(src), offset);
481  } else if constexpr (TypeT == kStreamType) {
482  thread_local std::stringstream ss;
483  ss.clear();
484  ss.str("");
485 
486  ss << deref(src);
487  const std::string& str = ss.str();
488  des = Bytes::deep_copy(reinterpret_cast<const uint8_t*>(str.data()), str.size(), offset);
489  } else if constexpr (TypeT == kStandardType) {
490  const auto* src_ptr = reinterpret_cast<const uint8_t*>(&deref(src));
491  des = Bytes::deep_copy(src_ptr, sizeof(RealType), offset);
492  } else if constexpr (TypeT == kStandardPtrType) {
493  if VUNLIKELY (offset > 0) {
494  VLOG_T("Serializer: Standard ptr does not support offset.");
495  return false;
496  }
497 
498  const auto* src_ptr = reinterpret_cast<const uint8_t*>(src);
499  constexpr size_t kSize = sizeof(std::remove_pointer_t<T>);
500 
501  if (des.is_loaned() && des.size() >= kSize) {
502  std::memcpy(des.data(), src_ptr, kSize);
503  } else {
504  des = Bytes::shallow_copy(src_ptr, kSize);
505  }
506  } else {
507  static_assert(Traits::ExpectFalse<T>(), "Not support serialize.");
508  return false;
509  }
510 
511  return true;
512 }
513 
514 template <typename T>
515 inline bool serialize(const T& src, Bytes& des) {
516  constexpr auto kType = get_type_of<T>();
517 
518  return serialize<kType>(src, des, TransportType::kUnknown);
519 }
520 
521 template <Type TypeT, typename T>
522 inline bool deserialize(const Bytes& src, T& des, [[maybe_unused]] TransportType transport) {
523  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
524 
525  if constexpr (TypeT == kBytesType) {
526  des = src;
527  return true;
528  } else if constexpr (TypeT == kDynamicType) {
529  try {
530  using ReturnT = decltype(deref(des) << src);
531 
532  if constexpr (std::is_convertible_v<ReturnT, bool>) {
533  if VUNLIKELY (!(deref(des) << src)) {
534  VLOG_T("Serializer: Dynamic deserialize failed.");
535  return false;
536  }
537  } else {
538  deref(des) << src;
539  }
540  } catch (const std::exception& e) { // LCOV_EXCL_LINE GCOVR_EXCL_LINE
541  VLOG_T("Serializer: Dynamic deserialize threw: ", e.what(), "."); // LCOV_EXCL_LINE GCOVR_EXCL_LINE
542  return false; // LCOV_EXCL_LINE GCOVR_EXCL_LINE
543  }
544  } else if constexpr (TypeT == kCdrType) {
545  if (transport == TransportType::kDds) {
546  if VUNLIKELY (!src.is_ptr()) {
547  VLOG_T("Serializer: Fastcdr src is not ptr.");
548  return false;
549  }
550 
551  deref(des) = *src.to_ptr<RealType>();
552  } else {
553  if constexpr (VLINK_HAS_MEMBER(RealType, getCdrSerializedSize(deref(des)))) {
554  eprosima::fastcdr::FastBuffer buffer(reinterpret_cast<char*>(const_cast<uint8_t*>(src.data())), src.size());
555 #if FASTCDR_VERSION_MAJOR >= 2
558 #else
560 #endif
561  deref(des).deserialize(cdr);
562  } else {
563  VLOG_W("Serializer: FastBuffer deserialize is not supported without dds(v3).");
564  return false;
565  }
566  }
567  } else if constexpr (TypeT == kProtoType) {
568  if (!src.empty()) {
569  if VUNLIKELY (!deref(des).ParseFromArray(src.data(), src.size())) {
570  VLOG_T("Serializer: Protobuf deserialize failed.");
571  return false;
572  }
573  } else {
574  deref(des).Clear();
575  }
576  } else if constexpr (TypeT == kProtoPtrType) {
577  if (!src.empty()) {
578  if VUNLIKELY (!des->ParseFromArray(src.data(), src.size())) {
579  VLOG_T("Serializer: Protobuf ptr deserialize failed.");
580  return false;
581  }
582  } else {
583  des->Clear();
584  }
585  } else if constexpr (TypeT == kFlatTableType) {
586  deref(des) = RealType{};
587 
588  if VLIKELY (!src.empty()) {
589  flatbuffers::Verifier verifier(src.data(), src.size());
590 
591  if VUNLIKELY (!verifier.VerifyBuffer<typename T::TableType>(nullptr)) {
592  VLOG_T("Serializer: Flatbuffers table deserialize failed.");
593  return false;
594  }
595 
596  auto target = flatbuffers::GetRoot<typename RealType::TableType>(src.data());
597  target->UnPackTo(&deref(des));
598  }
599  } else if constexpr (TypeT == kFlatPtrType) {
600  flatbuffers::Verifier verifier(src.data(), src.size());
601 
602  if VUNLIKELY (!verifier.VerifyBuffer<std::remove_pointer_t<T>>(nullptr)) {
603  VLOG_T("Serializer: Flatbuffers ptr verify failed.");
604  return false;
605  }
606 
607  des = const_cast<T>(flatbuffers::GetRoot<std::remove_pointer_t<T>>(src.data()));
608 
609  if VUNLIKELY (!des) {
610  VLOG_T("Serializer: Flatbuffers ptr deserialize failed.");
611  return false;
612  }
613  } else if constexpr (TypeT == kCustomType) {
614  try {
615  using ReturnT = decltype(deref(des) << src);
616 
617  if constexpr (std::is_convertible_v<ReturnT, bool>) {
618  if VUNLIKELY (!(deref(des) << src)) {
619  VLOG_T("Serializer: Custom deserialize failed.");
620  return false;
621  }
622  } else {
623  deref(des) << src;
624  }
625  } catch (const std::exception& e) {
626  VLOG_T("Serializer: Custom deserialize threw: ", e.what(), ".");
627  return false;
628  }
629  } else if constexpr (TypeT == kStringType) {
630  if VLIKELY (!src.empty()) {
631  deref(des) = std::string(reinterpret_cast<const char*>(src.data()), src.size());
632  } else {
633  deref(des) = std::string();
634  }
635  } else if constexpr (TypeT == kCharsType) {
636  if VLIKELY (!src.empty()) {
637  des = reinterpret_cast<const char*>(src.data());
638  } else {
639  des = "";
640  }
641  } else if constexpr (TypeT == kStreamType) {
642  thread_local std::stringstream ss;
643  ss.clear();
644  ss.str(std::string(reinterpret_cast<const char*>(src.data()), src.size()));
645 
646  ss >> deref(des);
647 
648  if VUNLIKELY (ss.fail()) {
649  VLOG_T("Serializer: Stream deserialize failed.");
650  return false;
651  }
652  } else if constexpr (TypeT == kStandardType) {
653  if VLIKELY (!src.empty() && src.size() == sizeof(RealType)) {
654  std::memcpy(&deref(des), src.data(), src.size());
655  } else {
656  VLOG_T("Serializer: Standard layout deserialize failed.");
657  return false;
658  }
659  } else if constexpr (TypeT == kStandardPtrType) {
660  if VLIKELY (!src.empty() && src.size() == sizeof(std::remove_pointer_t<T>)) {
661  des = reinterpret_cast<T>(const_cast<uint8_t*>(src.data()));
662  } else {
663  VLOG_T("Serializer: Standard ptr layout deserialize failed.");
664  return false;
665  }
666  } else {
667  static_assert(Traits::ExpectFalse<T>(), "Not support deserialize.");
668  return false;
669  }
670 
671  return true;
672 }
673 
674 template <typename T>
675 inline bool deserialize(const Bytes& src, T& des) {
676  constexpr auto kType = get_type_of<T>();
677  return deserialize<kType>(src, des, TransportType::kUnknown);
678 }
679 
680 template <typename SrcT, typename DesT>
681 inline bool convert(const SrcT& src, DesT& des) {
682  static_assert(is_bytes_type<SrcT>() || is_bytes_type<DesT>(), "SrcT or DesT must be Bytes.");
683 
684  if constexpr (is_bytes_type<SrcT>() && is_bytes_type<DesT>()) {
685  des.shallow_copy(src);
686  return true;
687  } else if constexpr (is_bytes_type<DesT>()) {
688  return serialize(src, des);
689  } else {
690  return deserialize(src, des);
691  }
692 }
693 
694 template <typename T>
695 inline constexpr auto& deref(const T& t) noexcept {
696  if constexpr (Traits::IsSharedPtr<T>()) {
697  return *const_cast<T&>(t).get();
698  } else {
699  return const_cast<T&>(t);
700  }
701 }
702 
703 template <typename T>
704 inline constexpr bool is_bytes_type() noexcept {
705  return std::is_same_v<T, Bytes>;
706 }
707 
708 template <typename T>
709 inline constexpr bool is_dynamic_type() noexcept {
710  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
711  return VLINK_HAS_MEMBER(RealType, is_vlink_dynamic_data());
712 }
713 
714 template <typename T>
715 inline constexpr bool is_cdr_type() noexcept {
716  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
717 
718  return kVlinkHasFastcdr && ((VLINK_HAS_MEMBER(RealType, serialize(std::declval<eprosima::fastcdr::Cdr&>())) &&
719  VLINK_HAS_MEMBER(RealType, deserialize(std::declval<eprosima::fastcdr::Cdr&>()))) ||
720  Helpers::contains_substring(NameDetector::get<RealType>(), VLINK_FASTDDS_IDL_PREFIX));
721 }
722 
723 template <typename T>
724 inline constexpr bool is_proto_type() noexcept {
725  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
726  return kVlinkHasProtobuf && VLINK_HAS_MEMBER(RealType, SerializeToArray(0, 0)) &&
727  VLINK_HAS_MEMBER(RealType, ParseFromArray(0, 0));
728 }
729 
730 template <typename T>
731 inline constexpr bool is_proto_ptr_type() noexcept {
732  return kVlinkHasProtobuf && std::is_pointer_v<T> &&
733  VLINK_HAS_MEMBER(std::remove_pointer_t<T>, SerializeToArray(0, 0)) &&
734  VLINK_HAS_MEMBER(std::remove_pointer_t<T>, ParseFromArray(0, 0));
735 }
736 
737 template <typename T>
738 inline constexpr bool is_flat_table_type() noexcept {
739  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
740  return kVlinkHasFlatbuffers && std::is_base_of_v<flatbuffers::NativeTable, RealType>;
741 }
742 
743 template <typename T>
744 inline constexpr bool is_flat_builder_type() noexcept {
745  return kVlinkHasFlatbuffers && VLINK_HAS_MEMBER(T, fbb_) && VLINK_HAS_MEMBER(T, Finish());
746 }
747 
748 template <typename T>
749 inline constexpr bool is_flat_ptr_type() noexcept {
750  return kVlinkHasFlatbuffers && std::is_pointer_v<T> &&
751  std::is_base_of_v<flatbuffers::Table, std::remove_pointer_t<T>>;
752 }
753 
754 template <typename T>
755 inline constexpr bool is_custom_type() noexcept {
756  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
758 }
759 
760 template <typename T>
761 inline constexpr bool is_string_type() noexcept {
762  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
763  return std::is_same_v<RealType, std::string>;
764 }
765 
766 template <typename T>
767 inline constexpr bool is_chars_type() noexcept {
768  return !std::is_same_v<T, std::string> && std::is_constructible_v<std::string, T>;
769 }
770 
771 template <typename T>
772 inline constexpr bool is_stream_type() noexcept {
773  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
774  return !std::is_pointer_v<RealType> && Traits::Operatorable<std::stringstream, std::decay_t<RealType>>();
775 }
776 
777 template <typename T>
778 inline constexpr bool is_standard_type() noexcept {
779  using RealType = typename Traits::RemoveSharedPtr<T>::Type;
780  return !std::is_pointer_v<RealType> && std::is_trivial_v<RealType> && std::is_standard_layout_v<RealType>;
781 }
782 
783 template <typename T>
784 inline constexpr bool is_standard_ptr_type() noexcept {
785  return std::is_pointer_v<T> && std::is_trivial_v<std::remove_pointer_t<T>> &&
786  std::is_standard_layout_v<std::remove_pointer_t<T>>;
787 }
788 
789 } // namespace Serializer
790 
791 } // namespace vlink
Definition: serializer-inl.h:59
Type
Definition: serializer-inl.h:61
@ DDS_CDR
Definition: serializer-inl.h:62
Definition: serializer-inl.h:66
Type
Definition: serializer-inl.h:68
@ DEFAULT_ENDIAN
Definition: serializer-inl.h:70
@ DDS_CDR
Definition: serializer-inl.h:69
Cdr(FastBuffer &, int, int)
Definition: serializer-inl.h:73
Definition: serializer-inl.h:54
FastBuffer(char *, size_t)
Definition: serializer-inl.h:56
#define VLOG_W(...)
Definition: logger.h:787
#define VLOG_T(...)
Definition: logger.h:781
#define VUNLIKELY(...)
Short alias for VLINK_UNLIKELY.
Definition: macros.h:289
#define VLIKELY(...)
Short alias for VLINK_LIKELY.
Definition: macros.h:284
Compile-time codec detection and dispatch for VLink message payloads.
Definition: serializer-inl.h:52
Definition: serializer-inl.h:119
Definition: serializer-inl.h:99
Definition: serializer-inl.h:126
const uint8_t * GetBufferPointer() const
Definition: serializer-inl.h:129
void Finish() const
Definition: serializer-inl.h:135
void PushBytes(const uint8_t *, size_t)
Definition: serializer-inl.h:133
size_t GetSize() const
Definition: serializer-inl.h:127
const uint8_t * GetCurrentBufferPointer() const
Definition: serializer-inl.h:131
Definition: serializer-inl.h:140
Definition: serializer-inl.h:138
Definition: serializer-inl.h:142
bool VerifyBuffer(void *)
Definition: serializer-inl.h:146
Verifier(const uint8_t *, size_t)
Definition: serializer-inl.h:143
Definition: serializer-inl.h:101
static T * Create(Arena *)
Definition: serializer-inl.h:103
#define VLINK_HAS_MEMBER(T, member)
Macro Definitions
Definition: traits.h:316