29 #include <type_traits>
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"
38 #ifndef VLINK_FASTDDS_IDL_PREFIX
39 #define VLINK_FASTDDS_IDL_PREFIX "dds::"
44 #if __has_include(<fastcdr/Cdr.h>)
45 [[maybe_unused]]
static constexpr
bool kVlinkHasFastcdr =
true;
47 #include <fastcdr/Cdr.h>
49 #define FASTCDR_VERSION_MAJOR 1
50 [[maybe_unused]]
static constexpr
bool kVlinkHasFastcdr =
false;
78 #if __has_include(<google/protobuf/message_lite.h>)
79 [[maybe_unused]]
static constexpr
bool kVlinkHasProtobuf =
true;
81 #include <google/protobuf/message_lite.h>
83 #if __has_include(<google/protobuf/stubs/common.h>)
84 #include <google/protobuf/stubs/common.h>
87 #if __has_include(<google/protobuf/arena.h>)
88 #include <google/protobuf/arena.h>
93 #ifndef GOOGLE_PROTOBUF_VERSION
94 #define GOOGLE_PROTOBUF_VERSION 0
97 [[maybe_unused]]
static constexpr
bool kVlinkHasProtobuf =
false;
102 template <
typename T>
112 #if __has_include(<flatbuffers/flatbuffers.h>)
113 [[maybe_unused]]
static constexpr
bool kVlinkHasFlatbuffers =
true;
115 #include <flatbuffers/flatbuffers.h>
117 [[maybe_unused]]
static constexpr
bool kVlinkHasFlatbuffers =
false;
121 template <
typename ReturnT,
typename T>
122 [[maybe_unused]]
static const ReturnT* GetRoot(
const T&) {
145 template <
typename T>
162 template <
typename T>
164 if constexpr (is_bytes_type<T>()) {
166 }
else if constexpr (is_dynamic_type<T>()) {
168 }
else if constexpr (is_cdr_type<T>()) {
170 }
else if constexpr (is_proto_type<T>()) {
172 }
else if constexpr (is_proto_ptr_type<T>()) {
174 }
else if constexpr (is_flat_table_type<T>()) {
176 }
else if constexpr (is_flat_ptr_type<T>()) {
178 }
else if constexpr (is_flat_builder_type<T>()) {
180 }
else if constexpr (is_custom_type<T>()) {
182 }
else if constexpr (is_string_type<T>()) {
184 }
else if constexpr (is_chars_type<T>()) {
186 }
else if constexpr (is_standard_type<T>()) {
188 }
else if constexpr (is_standard_ptr_type<T>()) {
190 }
else if constexpr (is_stream_type<T>()) {
197 template <Type TypeT,
typename T>
198 inline static constexpr
SchemaType get_schema_type() noexcept {
205 if constexpr (RealType::kZerocopyTypes) {
211 return RealType::get_schema_type();
224 template <
typename T>
225 inline static constexpr
SchemaType get_schema_type() noexcept {
226 constexpr
auto kType = get_type_of<T>();
228 return get_schema_type<kType, T>();
231 template <Type TypeT,
typename T>
234 using NamedType = std::remove_pointer_t<RealType>;
239 return "vlink::DynamicData";
243 #if GOOGLE_PROTOBUF_VERSION >= 6030000
244 return std::string(RealType{}.GetTypeName());
246 return RealType{}.GetTypeName();
249 #if GOOGLE_PROTOBUF_VERSION >= 6030000
250 return std::string(std::remove_pointer_t<T>().GetTypeName());
252 return std::remove_pointer_t<T>().GetTypeName();
255 using TableType =
typename RealType::TableType;
257 return TableType::GetFullyQualifiedName();
259 std::string name = NameDetector::get<TableType>().data();
264 using TableType =
typename RealType::Table;
266 return TableType::GetFullyQualifiedName();
268 std::string name = NameDetector::get<TableType>().data();
273 using TableType = std::remove_pointer_t<T>;
275 return TableType::GetFullyQualifiedName();
277 std::string name = NameDetector::get<TableType>().data();
283 }
else if constexpr (NameDetector::is_support<NamedType>()) {
284 return NameDetector::get<NamedType>().data();
290 template <
typename T>
292 constexpr
auto kType = get_type_of<T>();
294 return get_serialized_type<kType, T>();
297 template <Type TypeT,
typename T>
305 }
else if constexpr (TypeT ==
kCdrType) {
307 return RealType::getCdrSerializedSize(
deref(src));
313 return deref(src).ByteSizeLong();
315 return deref(src).ByteSize();
319 return src->ByteSizeLong();
321 return src->ByteSize();
326 return src.fbb_.GetSize();
331 return deref(src).get_serialized_size();
350 template <
typename T>
352 constexpr
auto kType = get_type_of<T>();
354 return get_serialized_size<kType>(src);
357 template <Type TypeT,
typename T>
359 [[maybe_unused]] uint8_t offset) {
365 using ReturnT = decltype(
deref(src) >> des);
367 if constexpr (std::is_convertible_v<ReturnT, bool>) {
369 VLOG_T(
"Serializer: Dynamic serialize failed.");
375 }
else if constexpr (TypeT ==
kCdrType) {
381 size_t target_size = RealType::getCdrSerializedSize(
deref(src));
387 VLOG_W(
"Serializer: FastBuffer serialize is not supported without dds(v3).");
393 #if FASTCDR_VERSION_MAJOR >= 2
399 deref(src).serialize(cdr);
404 size_t target_size =
deref(src).ByteSizeLong();
410 size_t target_size =
deref(src).ByteSize();
419 VLOG_T(
"Serializer: Protobuf serialize failed.");
425 size_t target_size = src->ByteSizeLong();
431 size_t target_size = src->ByteSize();
440 VLOG_T(
"Serializer: Protobuf ptr serialize failed.");
453 src.fbb_.Finish(
const_cast<T&
>(src).Finish());
458 des =
Bytes::deep_copy(src.fbb_.GetBufferPointer(), src.fbb_.GetSize(), offset);
463 using ReturnT = decltype(
const_cast<RealType&
>(
deref(src)) >> des);
465 if constexpr (std::is_convertible_v<ReturnT, bool>) {
467 VLOG_T(
"Serializer: Custom serialize failed.");
471 const_cast<RealType&
>(
deref(src)) >> des;
480 des =
Bytes::deep_copy(
reinterpret_cast<const uint8_t*
>(src), std::strlen(src), offset);
482 thread_local std::stringstream ss;
487 const std::string& str = ss.str();
488 des =
Bytes::deep_copy(
reinterpret_cast<const uint8_t*
>(str.data()), str.size(), offset);
490 const auto* src_ptr =
reinterpret_cast<const uint8_t*
>(&
deref(src));
494 VLOG_T(
"Serializer: Standard ptr does not support offset.");
498 const auto* src_ptr =
reinterpret_cast<const uint8_t*
>(src);
499 constexpr
size_t kSize =
sizeof(std::remove_pointer_t<T>);
502 std::memcpy(des.
data(), src_ptr, kSize);
514 template <
typename T>
516 constexpr
auto kType = get_type_of<T>();
521 template <Type TypeT,
typename T>
530 using ReturnT = decltype(
deref(des) << src);
532 if constexpr (std::is_convertible_v<ReturnT, bool>) {
534 VLOG_T(
"Serializer: Dynamic deserialize failed.");
540 }
catch (
const std::exception& e) {
541 VLOG_T(
"Serializer: Dynamic deserialize threw: ", e.what(),
".");
544 }
else if constexpr (TypeT ==
kCdrType) {
547 VLOG_T(
"Serializer: Fastcdr src is not ptr.");
555 #if FASTCDR_VERSION_MAJOR >= 2
561 deref(des).deserialize(cdr);
563 VLOG_W(
"Serializer: FastBuffer deserialize is not supported without dds(v3).");
570 VLOG_T(
"Serializer: Protobuf deserialize failed.");
579 VLOG_T(
"Serializer: Protobuf ptr deserialize failed.");
586 deref(des) = RealType{};
592 VLOG_T(
"Serializer: Flatbuffers table deserialize failed.");
596 auto target = flatbuffers::GetRoot<typename RealType::TableType>(src.
data());
597 target->UnPackTo(&
deref(des));
603 VLOG_T(
"Serializer: Flatbuffers ptr verify failed.");
607 des =
const_cast<T
>(flatbuffers::GetRoot<std::remove_pointer_t<T>>(src.
data()));
610 VLOG_T(
"Serializer: Flatbuffers ptr deserialize failed.");
615 using ReturnT = decltype(
deref(des) << src);
617 if constexpr (std::is_convertible_v<ReturnT, bool>) {
619 VLOG_T(
"Serializer: Custom deserialize failed.");
625 }
catch (
const std::exception& e) {
626 VLOG_T(
"Serializer: Custom deserialize threw: ", e.what(),
".");
631 deref(des) = std::string(
reinterpret_cast<const char*
>(src.
data()), src.
size());
633 deref(des) = std::string();
637 des =
reinterpret_cast<const char*
>(src.
data());
642 thread_local std::stringstream ss;
644 ss.str(std::string(
reinterpret_cast<const char*
>(src.
data()), src.
size()));
649 VLOG_T(
"Serializer: Stream deserialize failed.");
656 VLOG_T(
"Serializer: Standard layout deserialize failed.");
660 if VLIKELY (!src.
empty() && src.
size() ==
sizeof(std::remove_pointer_t<T>)) {
661 des =
reinterpret_cast<T
>(
const_cast<uint8_t*
>(src.
data()));
663 VLOG_T(
"Serializer: Standard ptr layout deserialize failed.");
674 template <
typename T>
676 constexpr
auto kType = get_type_of<T>();
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.");
684 if constexpr (is_bytes_type<SrcT>() && is_bytes_type<DesT>()) {
685 des.shallow_copy(src);
687 }
else if constexpr (is_bytes_type<DesT>()) {
694 template <
typename T>
695 inline constexpr
auto&
deref(
const T& t) noexcept {
697 return *
const_cast<T&
>(t).
get();
699 return const_cast<T&
>(t);
703 template <
typename T>
705 return std::is_same_v<T, Bytes>;
708 template <
typename T>
714 template <
typename T>
723 template <
typename T>
726 return kVlinkHasProtobuf &&
VLINK_HAS_MEMBER(RealType, SerializeToArray(0, 0)) &&
730 template <
typename T>
732 return kVlinkHasProtobuf && std::is_pointer_v<T> &&
737 template <
typename T>
740 return kVlinkHasFlatbuffers && std::is_base_of_v<flatbuffers::NativeTable, RealType>;
743 template <
typename T>
748 template <
typename T>
750 return kVlinkHasFlatbuffers && std::is_pointer_v<T> &&
751 std::is_base_of_v<flatbuffers::Table, std::remove_pointer_t<T>>;
754 template <
typename T>
760 template <
typename T>
763 return std::is_same_v<RealType, std::string>;
766 template <
typename T>
768 return !std::is_same_v<T, std::string> && std::is_constructible_v<std::string, T>;
771 template <
typename T>
777 template <
typename T>
780 return !std::is_pointer_v<RealType> && std::is_trivial_v<RealType> && std::is_standard_layout_v<RealType>;
783 template <
typename T>
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>>;
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
Fixed-size 128-byte buffer holder with SBO, five ownership modes and integrated codecs.
Definition: bytes.h:120
bool empty() const noexcept
Reports whether the buffer is logically empty.
Definition: bytes.h:861
bool is_loaned() const noexcept
Reports whether the buffer is an iceoryx loan that VLink must not free.
Definition: bytes.h:859
static Bytes shallow_copy_ptr(void *data) noexcept
Wraps an opaque pointer as a zero-size pointer carrier.
static Bytes shallow_copy(uint8_t *data, size_t size) noexcept
Wraps an external mutable buffer as a non-owning alias.
bool is_ptr() const noexcept
Reports whether this carrier merely wraps an opaque pointer.
Definition: bytes.h:879
size_t size() const noexcept
Returns the size of the payload region in bytes.
Definition: bytes.h:849
uint8_t * data() noexcept
Returns a mutable pointer to the start of the payload (post-offset).
Definition: bytes.h:841
static Bytes create(size_t size, uint8_t offset=0) noexcept
Allocates an owned buffer of the requested size with an optional header offset.
static Bytes deep_copy(uint8_t *data, size_t size, uint8_t offset=0) noexcept
Produces an owned copy of an external mutable buffer.
T * to_ptr() const noexcept
Reinterprets the backing pointer as T*.
Definition: bytes.h:882
#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
constexpr bool contains_substring(std::string_view sv, std::string_view needle) noexcept
Constexpr substring search.
Definition: helpers.h:431
VLINK_EXPORT void replace_string(std::string &str, const std::string &from, const std::string &to) noexcept
Replaces all occurrences of from in str with to in place.
constexpr std::string_view get() noexcept
Returns the trimmed compile-time identifier for TypeT.
Definition: name_detector.h:603
constexpr bool is_proto_ptr_type() noexcept
Reports whether T is a raw pointer to a Protobuf-like message.
Definition: serializer-inl.h:731
std::string get_serialized_type() noexcept
Returns the serialised type-name string for T with explicit codec tag.
Definition: serializer-inl.h:291
constexpr bool is_dynamic_type() noexcept
Reports whether T is a VLink dynamic data type.
Definition: serializer-inl.h:709
constexpr bool is_chars_type() noexcept
Reports whether std::string is constructible from T (but T is not string).
Definition: serializer-inl.h:767
bool deserialize(const Bytes &src, T &des, [[maybe_unused]] TransportType transport)
Definition: serializer-inl.h:522
constexpr Type get_type_of() noexcept
Resolves the codec Type for T at compile time.
Definition: serializer-inl.h:163
Type
Identifies the codec to use for a given C++ message type.
Definition: serializer.h:154
@ kStandardPtrType
Pointer to trivial standard-layout struct (POD pointer).
Definition: serializer.h:169
@ kCustomType
User-defined codec via operator>>/<<.
Definition: serializer.h:158
@ kDynamicType
VLink dynamic typed data.
Definition: serializer.h:157
@ kFlatTableType
FlatBuffers NativeTable (object API).
Definition: serializer.h:162
@ kCharsType
C string / char*.
Definition: serializer.h:166
@ kUnknownType
Unsupported type; is_supported() returns false.
Definition: serializer.h:155
@ kBytesType
Bytes – raw byte pass-through.
Definition: serializer.h:156
@ kProtoPtrType
Protobuf-like raw pointer; caller-owned.
Definition: serializer.h:161
@ kStandardType
Trivial standard-layout struct (POD value).
Definition: serializer.h:168
@ kStringType
std::string – UTF-8 text.
Definition: serializer.h:165
@ kFlatBuilderType
FlatBuffers builder (fbb_ + Finish()).
Definition: serializer.h:164
@ kStreamType
Stream-serialisable via std::stringstream.
Definition: serializer.h:167
@ kProtoType
Protobuf-like value.
Definition: serializer.h:160
@ kCdrType
FastDDS CDR via serialize(Cdr&) / deserialize(Cdr&).
Definition: serializer.h:159
@ kFlatPtrType
Pointer to flatbuffers::Table (zero-copy view).
Definition: serializer.h:163
constexpr auto & deref(const T &t) noexcept
Dereferences a value, unwrapping std::shared_ptr when present.
Definition: serializer-inl.h:695
constexpr bool is_supported(Type type) noexcept
Reports whether type identifies a usable codec.
Definition: serializer-inl.h:160
constexpr bool is_custom_type() noexcept
Reports whether T provides a custom operator>>/<< codec.
Definition: serializer-inl.h:755
size_t get_serialized_size(const T &src) noexcept
Returns a serialised-size hint for src with explicit codec tag.
Definition: serializer-inl.h:298
bool convert(const SrcT &src, DesT &des)
Converts between two types where at least one side is Bytes.
Definition: serializer-inl.h:681
constexpr bool is_cdr_type() noexcept
Reports whether T is a FastDDS CDR-serialisable type.
Definition: serializer-inl.h:715
constexpr bool is_proto_type() noexcept
Reports whether T is a Protobuf-like message value type.
Definition: serializer-inl.h:724
std::string get_serialized_type() noexcept
Returns the serialised type-name string for T with explicit codec tag.
Definition: serializer-inl.h:232
bool serialize(const T &src, Bytes &des, [[maybe_unused]] TransportType transport, [[maybe_unused]] uint8_t offset)
Definition: serializer-inl.h:358
constexpr bool is_flat_ptr_type() noexcept
Reports whether T is a raw pointer to a flatbuffers::Table.
Definition: serializer-inl.h:749
constexpr bool is_flat_builder_type() noexcept
Reports whether T is a FlatBuffers builder type.
Definition: serializer-inl.h:744
constexpr bool is_standard_ptr_type() noexcept
Reports whether T is a pointer to a trivial standard-layout type.
Definition: serializer-inl.h:784
constexpr bool is_standard_type() noexcept
Reports whether T is a trivial standard-layout value (POD).
Definition: serializer-inl.h:778
constexpr bool is_flat_table_type() noexcept
Reports whether T is a FlatBuffers NativeTable type.
Definition: serializer-inl.h:738
constexpr bool is_string_type() noexcept
Reports whether T is std::string after unwrapping shared_ptr.
Definition: serializer-inl.h:761
constexpr bool is_bytes_type() noexcept
Reports whether T is exactly Bytes.
Definition: serializer-inl.h:704
constexpr bool is_stream_type() noexcept
Reports whether T supports bidirectional std::stringstream streaming.
Definition: serializer-inl.h:772
SchemaType
Coarse runtime schema family used by discovery, bag metadata and proxy routing.
Definition: types.h:207
@ kZeroCopy
Decode through the VLink zero-copy structs.
@ kProtobuf
Decode through the Protocol Buffers stack.
@ kFlatbuffers
Decode through the FlatBuffers stack.
@ kRaw
Treat the payload as opaque bytes.
TransportType
Enumeration of every transport backend recognised by VLink.
Definition: types.h:128
@ kUnknown
Unknown or unsupported transport.
@ kDds
Fast-DDS RTPS (dds://).
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
Type trait that always derives from std::false_type for any T.
Definition: traits.h:103
Detects whether T is (or derives from) a std::shared_ptr specialisation.
Definition: traits.h:193
Detects whether OT supports stream insertion (<<) and extraction (>>) with T.
Definition: traits.h:167
T Type
Resolved type after optional shared_ptr removal.
Definition: traits.h:211
#define VLINK_HAS_MEMBER(T, member)
Macro Definitions
Definition: traits.h:316